OrderBy - 究竟是如何实现的?

时间:2013-11-25 21:19:08

标签: c#

.NET如何知道哪些字段需要订购?根据定义: Enumerable.OrderBy方法(IEnumerable,Func) 字段由Tkey选择,但只提供字段的值而不是字段本身。 这是一个例子:

class Cls1
{
  public string a;
  public string b;
}

string keysel2(Cls1 c)
{
  return c.a;
}

string keysel3(Cls1 c)
{
  return c.b;
}

以后我们有:

List<Cls1> cls1list = new List<Cls1>();

void f()
{
 cls1list.Add(new Cls1 { a = "3", b = "a" });
 cls1list.Add(new Cls1 { a = "2", b = "b" });
 cls1list.Add(new Cls1 { a = "1", b = "c" });

 IEnumerable<Cls1> cls2list = cls1list.OrderBy(keysel2);

 foreach (Cls1 item in cls2list)
 {
    string s = item.a;
    string s1 = item.b;
 }
}

因此,OrderBy中没有任何内容直接链接到Cls1的成员字段。编译器如何获取有关实际字段的信息?

2 个答案:

答案 0 :(得分:4)

您对OrderBy的调用如下:cls1list.OrderBy(keysel2);

对于cls1list集合中的每个项目,OrderBy将调用keysel2,它返回'a'字符串。 OrderBy然后在成对的字符串上调用Compare,这允许它对项目进行排序。

您可能没有意识到OrderBy表达式的keysel2部分是指一个方法,该方法在集合中的每个对象上调用 - 另一种编写方法,在功能上等同于:

cls1list.OrderBy(item => keysel2(item));

OrderBy正在做这样的事情:

foreach(Cls1 currentItem in items)
{
    Cls1 nextItem = ... (get the next item from items by magic)
    object currentKey = keysel2(currentItem); // This returns a string into currentKey
    object nextKey = keysel2(nextItem); // This returns a string into currentKey

    if(currentKey.Compare(nextKey))
    {
       ... // Swap the items (or not, depending on the ordering you want)
       // Note that OrderBy hasn't looked into the Cls1 items itself at all, it's just looked at the objects it got back from calling keysel2.

    }
}

关于将密钥选择委托传递给OrderBy的观点是,它意味着OrderBy根本不需要知道它正在排序的对象类型 - 它需要知道的是,如果它调用密钥 - select方法,该方法将返回可用于确定对象进入的顺序的东西。您可以将键选择委托视为一种“解释器” - 它可以理解您的Cls1对象并可以将它们转换为一般的东西 - 订单可以理解的目的。

答案 1 :(得分:1)

Func<Cls1,string>接受Cls1类型的参数并返回一个字符串。 cls1list.OrderBy(keysel2);是合法的,因为方法组keysel2可隐式转换为Func<Cls1,string>。在这里,我定义了一个类似的方法并拉出相同的技巧。最后我们得到的是一个字符串:

    F(keysel2);//Invoke

    string F(Func<Cls1, string> func)
    {
        string orderByResult = func(new Cls1 { a = "4", b = "d" });
        return orderByResult;
    }

Func<TSource, TKey>的实施与OrderBy无关。代表只需要与Func<,>兼容。 OrderBy将为集合中的每个项调用委托。它将使用委托返回的值来执行它的操作,在本例中是命令。