下面讨论的情况基于.NET 框架3.5以上版本。如果现在有一个类叫Cat, 然后我创建了该类的一个实例,然后先调用A方法,然后在A方法的返回值上调用B方法。Cat cat = new Cat();
cat.A().B();如果这样的调用可以成功编译的话,大家都知道,A方法或B方法只有两种可能:要么在所在类中已经定义,要么被定义为一个扩展方法。以A方法为例,我有下面两种说法,不知道对不对,想请大家帮我确认下:前提:如果Cat类中没有定义A方法,那我就说:
1)因为A方法是扩展方法,所以A方法才允许被调用;
2)A方法之所以允许被调用是因为A方法是扩展方法;令我想到上面这两句话是否正确的原因是今天和同事争论了一个话题。
大家都知道,C#自从有了扩展方法后,我们可以在不对类做任何扩充的情况下就可以对其进行扩展。LINQ为我们提供了很好的例子,比如如下的语句:LINQ语句示例:
IEnumerable<object> postEnumerable =
    context.GetTable<Post>().Where(p => p.BlogId > 100).Select(p => new { p.BlogId, p.Blog });
大家都知道,Where方法以及Select方法都是定义在IEnumerable<T>接口上的扩展方法,IEnumerable<T>接口接口本身没有定义这两个方法。我和同事因为如下的观点不同而发生争吵:
我的说法是:
1)LINQ之所以可以这样子实现方法的连续调用是因为扩展方法的原因;
2)没有扩展方法我们就不能实现像上面这样的连续调用,因为Where方法以及Select方法并没有在所在类或接口中定义过;
而我同事不同意我的观点,他的意思是,能不能调用取决于方法的返回值类型。反正我现在是彻底弄糊涂了,感觉像是有点哲学的意味了。我感觉我现在思考的问题的角度和他不一致,我感觉自己是站在辨证唯物注意哲学的叫的角度上来说话的,而他是怎么考虑的我到现在还没弄清楚。我觉得是这样的:如果我能掉某个方法A,只有两种可能性,方法A要么是所在类的一个成员,要么是一个扩展方法。而现在如果这个A方法不是所在类的成员;那么我就认为:
1)方法A之所以可以被正常调用是因为它是一个扩展方法;
2)或者说因为A方法是一个扩展方法,所以它才能被调用;我这样的理解对吗?

解决方案 »

  1.   

    string s=....;
    s.substring(0,2).trim();
      

  2.   

    被楼主搞糊涂了,语句过于复杂,不过可以证明你同事的观点是对的
    如下定义Cat即可像上面那样调用,无需扩展方法
    class Cat
        {
            public Cat A()
            {
                return new Cat();
            }        public void B()
            {
            }
        }
      

  3.   

    都没错。好比你在说Cat.A(),而你同事在说Cat.A().B().
      

  4.   

    cat.A().B();
    是不是应当这样理解,取决于你的A方法的返回类型是否有(B方法或扩展方法且能调用)
      

  5.   

    是的,执行的顺序是,.net先调用cat.A()然后返回类型再调用B(),你可以输出log看执行顺序
      

  6.   

    实际上我想我和我同事都清楚对于我上面举的例子:
    IEnumerable<object> postEnumerable =
        context.GetTable<Post>().Where(p => p.BlogId > 100).Select(p => new { p.BlogId, p.Blog });Where和Select方法的返回值都是一样的IEnumerable接口。所以,我以为我们讨论的基础是不需要关心方法返回值的类型的。不知道我有没有说清楚。
      

  7.   

    执行的顺序是先调用A()然后返回类型再调用B(),你可以输出log看执行顺序
      

  8.   

    以前曾经参考过《LINQ实战》,里面明确说明何为扩展方法。
    举个例子,比如说我要为String定义一个扩展方法:
    public static string Check(this string data)
    {
        if(data!=null&&data.trim()!="")
            return data.ToSring();
        else
            return "Is Null";
    }调用
        string data1="a";
        string data2=NULL;
        Console.Write(data1.Check());//输出a
        Console.Write(data2.Check());//输出Is Null其实扩展方法只是在类的外部增加的额外的方法,跟普通方法没什么区别。
    而在LINQ里面的WHERE SELECT这些也属于扩展方法。
    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source,Func<Tsource,Boolean> predicate)
    {
        foreach(TSource element in source)
        {
            if(predicate(element))
                 yield return element;
         }
    }
      

  9.   

    所以我也觉得阁下说得没错,正因为A()是一个扩展方法所以在Cat类里面未被定义也能调用
      

  10.   

    cat.A().B();
    //应该是A方法返回某个对象,然后又调用了该对象的B方法
      

  11.   


    1)方法A之所以可以被正常调用是因为它是一个扩展方法;
    2)或者说因为A方法是一个扩展方法,所以它才能被调用;我这样的理解对吗?
    你这2句话表达的意思没有什么不同,且都不准确。其实这个模型中涉及到2个概念:
    一:扩展方法
    一个方法被一个对象或者一个类直接调用(静态方法),则说明要么这个方法在类中有定义,要么就是在类的外部被扩展了(扩展方法)。二:连续调用思想
    其实这个思想借用了类似jquery的方式,就是在定义方法的时候设法让方法返回定义自己的一个对象。说白了就是我在A类中定义一个方法,我设法让这个方法的返回值是A的一个对象,这样就可以在调用方法的时候直接利用返回值再继续调用。这是2个东西,当然组合在一起用效果更佳,但是不要混为一谈。