我试图了解LINQ并对使用它充满信心。我正在努力的是要求的参数。例如:
var sortedWords = words.OrderBy(a=>a.Length)
words
是一个数组集合。 OrderBy
的intellisense说:
Func<string, TKey> keyselector
func
执行方法,string
是值,TKey
是一个键。
在示例http://msdn.microsoft.com/en-us/vcsharp/aa336756.aspx#thenBySimple(ThenBy
- Comparer)中,我们通过说a => a.Length
来比较长度。我理解语法,但这与intellisense要求的内容有什么关系?
由于所有的泛型,我倾向于发现方法签名和智能感知不可读。
感谢。
答案 0 :(得分:6)
如果您了解.NET / C#中lambda expressions的性质,那么类型(由Intellisense显示)是有意义的。否则,新人确实有点奇怪。首先考虑keySelector的类型, Func&lt; TSource,TKey&gt; 只是一个委托。在C#3.0之前,您可以通过将委托作为参数传递来调用此类方法,例如:
IEnumerable<string> sortedWords = words.OrderBy(new Func<string, int>(mySelectorMethod));
其中mySelectorMethod是普通方法的名称,该方法将字符串作为参数并返回 int 。 (作为一个侧面点,我想你可以使用匿名委托,但是现在不要去那里。)另外,请注意这个例子纯粹是说明性的,因为LINQ几乎总是与.NET 3.5 / C#3.0一起使用(虽然我相信它可以与.NET 2.0 / C#2.0中的任何一个一起使用 - 如果我错了,有人会纠正我。从C#3.0开始,方法可以内联定义为lambda表达式,这些表达式旨在用于这些情况。如果你想得到一个正确的介绍,请阅读有关lambda表达式(上面链接)的MSDN文章,但在这里我将简单描述在这个特定上下文中的用法。正如您所说,您的代码(在C#3.0中)类似于以下内容:
var sortedWords = words.OrderBy(a => a.Length);
表达式a => a.Length
的部分是 lambda表达式,它实际上只是用于声明内联函数的简写。 lambda表达式的语法在很大程度上非常简单;在=&gt;的左边参数是通过(arg1,arg2,arg3)的形式指定的,但由于在这种情况下只有一个,你可以省略括号。在=&gt;的右侧是表达式,它是函数的返回值(更准确地说是lambda表达式)。或者,您可以在{和}中包含带有return语句的实际代码,但这通常是不必要的。我相信C#编译器所做的是将传递给OrderBy的参数识别为lambda表达式,然后将其编译为函数并为您创建并传递委托。请注意,lambda表达式也可以转换为 System.Linq.Expressions.Expression 对象(可访问的表达式树)而不是委托,但这是一种不太常见的用法。无论如何,这里的幕后工作有很多,但希望这至少应该澄清为什么类型是 Func&lt; TSource,TKey&gt; 以及它与lambda表达式的关系。正如我所说,如果你想更深入地了解LINQ / lambdas / delegates,请在MSDN上阅读......
答案 1 :(得分:5)
a => a.Length
我理解语法,但这与intellisense要求的内容有什么关系?
这段代码是lambda表达式。 lambda表达式是生成匿名方法(在本例中)或System.Linq.Expressions.Expression的便捷方式。让我们按部分分解。
Func<string, object>
。此类函数的参数是字符串,因此编译器确定 a 必须是字符串。程序员唯一需要提供的是名称。现在,考虑一下这个C#2.0 ......
IEnumerable<string> sortedWords =
Enumerable.OrderBy(words, delegate(string a) {return a.Length;});
使用C#3.0
IEnumerable<string> sortedWords = words
.OrderBy(a => a.Length);
答案 2 :(得分:1)
我认为IntelliSense实际上非常有用,特别是对于以Func<..>
类型作为参数的泛型方法,因为您可以看到类型和类型指导您了解该方法可能会做什么。
例如,OrderBy
的参数是IEnumerable<string>
作为'this'参数,这意味着我们有一些包含字符串集合的输入。第一个参数keySelector
的类型为Func<string, TKey>
,这意味着它是您提供的一些lambda表达式,用于指定如何从TKey
获取string
。
这已经表明该方法可能会枚举集合中的所有项(字符串),并且可以使用keySelector
从集合中的每个元素获取类型TKey
的值。名称TKey
已经表明它将使用此值来比较使用此计算键的元素(字符串)。但是,如果您查看另一个需要IComparer<TKey>
的重载,那么您可以确定这一点 - 此参数指定了有关如何比较类型TKey
的两个值的更多详细信息,因此函数< em>必须使用此键比较元素。
......这种关于类型的思考需要一些时间来习惯,但是一旦你学会了它,它就会非常有用。它在“功能”代码风格中更有用,它通常在C#3.0中使用大量泛型和lamdba表达式(在F#或其他函数语言中类似的东西)
答案 3 :(得分:0)
说实话,我从不真正担心智能感知。在我的Linqage早期让我搞砸了。因为我花了更多的时间来使用泛型和表达式,所以它开始有意义,但直到那时我才开始使用语法。
它想要的是一个lambda表达式,它告诉Linq为了对您的集合进行排序需要查找什么。
我觉得你,我的兄弟,在那里,很快就会有意义。
答案 4 :(得分:0)
OrderBy()
接受一个接受单个参数的函数的委托(在您的情况下, string
)并返回一个值用于替换 TKey
的类型。可能是因为您在IEnumerable<string>
上调用了方法,因此参数类型(字符串)已经确定,但委托类型只会被解析为Func<string,
int
>
在之后,它在完全指定时从lambda表达式中推断出它(即a => a.Length
)。如果你没有给解析器任何关于你想要什么作为排序键的线索,它只会在IntelliSense中显示 TKey ,直到它可以确定预期的类型。