扩展方法如何在后台工作?

时间:2010-06-08 09:30:42

标签: c# .net linq extension-methods

我只是对延伸方法机制背后的诅咒。我脑子里出现了一些问题和答案。

MyClass.OrderBy(x=>x.a).OrderBy(x=>x.b);

我猜测机制是第一个orderby方法工作,然后由成员命令然后在IEnumarable接口中返回已排序的项目然后下一个IEnumarable的Orderby方法将它们命令为b paramater。但是当我查看这个linq查询时我错了。

MyClass.Orderby(x=>x.a).ThenOrderBy(x=>x.b);

这有点不同,并告诉我,我错了。因为这不是由当时的b排序而且如果我是对的则不可能有这样的结果。这让我感到困惑......

类似的结构可以用扩展方法编写作为第一个查询,但第二个是不可能的。这证明我错了。你可以解释一下吗?

2 个答案:

答案 0 :(得分:6)

Others have explained如何在编译期间将扩展方法转换为静态方法,所以我不打算进入。

我认为你问的是OrderBy和ThenBy在顺序调用时如何设法产生正确的顺序,所以我将尝试回答你问题的这一部分。


扩展方法Enumerable.OrderBy返回IOrderedEnumerable,支持它的具体类是OrderedEnumerable,它在内部存储用于对可枚举进行排序的函数。

当您调用ThenBy时,您正在调用静态Enumerable.ThenBy方法并将OrderedEnumerable从第一次调用的输出传递给OrderBy,从而创建第二个OrderedEnumerable。第二个OrderedEnumerable将包含对第一次创建的父OrderedEnumerable的引用。

所以你所拥有的是一个OrderedEnumerable,它包含一个父OrderedEnumerable,每个都有为了排序而存储的相应函数。当您枚举它时,每个OrderedEnumerable首先委托它的父级,并且只有在父级无法分离正在排序的项目时才使用它自己的排序函数。显然,你没有理由不能拥有几个OrderedEnumerables的链,并且它总是最先调用它的排序函数。

我画了一个快速图表来尝试帮助解释:

link text http://i48.tinypic.com/smdf1g.png


我希望这是有道理的。我希望我没有混淆那里的情况,我想我已经把“可枚举”这个词搞得一团糟了。如果您需要更多详细信息,可以使用reflector来了解各种方法在幕后所做的工作。

答案 1 :(得分:1)

扩展方法只是语法糖,它们被编译好的IL中的实际静态方法调用所取代。

考虑这种扩展方法,检查字符串是否是有效的电子邮件。

    public static bool IsEmail(this string email)
    {
        if (email != null)
        {
            return Regex.IsMatch(email, "EmailPattern");
        }

        return false;
    }
在C#中的

我将这个扩展方法称为如下。

string str = "myname@server.com";
bool isValidEmail = str.IsEmail();

编译后,对str.IsEmail()的调用被IsEmail(str)替换;

如果是,MyClass.OrderBy(x=>x.a).OrderBy(x=>x.b);每个扩展方法都返回定义后续扩展方法的实例类型。这称为方法调用的链接,或者更恰当地称为fluent-interfacing

的技术