.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的成员字段。编译器如何获取有关实际字段的信息?
答案 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
将为集合中的每个项调用委托。它将使用委托返回的值来执行它的操作,在本例中是命令。