让我们来分析您的代码示例:
filenames.SelectMany(f =>
Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
.Cast<PluginClassAttribute>()
.Select(a => a.PluginType)
).ToList();
所以,我们开始与一个叫filenames
string[]
。我们调用阵列上的SelectMany
扩展方法,然后我们对结果调用ToList
:
filenames.SelectMany(
...
).ToList();
SelectMany
需要委托作为参数,在这种情况下,代表必须采取类型string
的一个参数作为输入,并返回IEnumerable<T>
(其中推断出T
的类型)。这是lambda表达式进入阶段:
filenames.SelectMany(f =>
Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
).ToList()
什么会发生在这里是为filenames
阵列中的每个元素,委托将被调用。 f
是输入参数,并且=>
右侧的内容是代表所指的方法体。在这种情况下,将调用Assembly.LoadFrom
作为数组中的文件名,使用参数f
将文件名传入LoadFrom
方法。在返回的AssemblyInstance
上,将调用GetCustomAttributes(typeof(PluginClassAttribute), true)
,它将返回一个Attribute
实例的数组。所以编译器不能推断出前面提到的T
的类型是Assembly
。
在返回的IEnumerable<Attribute>
上,将调用Cast<PluginClassAttribute>()
,返回IEnumerable<PluginClassAttribute>
。
所以现在我们有一个IEnumerable<PluginClassAttribute>
,我们调用Select
就可以了。该Select
方法类似于SelectMany
,但返回代替IEnumerable<T>
T
类型(这是由编译器推断出)的单个实例。该设置是相同的;在IEnumerable<PluginClassAttribute>
每个元素它将调用定义的委托,当前元素值传递到其中:
.Select(a => a.PluginType)
再次,a
是输入参数,a.PluginType
是方法体。因此,对于列表中的每个PluginClassAttribute
情况下,它会返回PluginType
属性的值(我将承担此属性的类型Type
的)。
摘要
如果我们的点点滴滴粘合在一起:
// process all strings in the filenames array
filenames.SelectMany(f =>
// get all Attributes of the type PluginClassAttribute from the assembly
// with the given file name
Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
// cast the returned instances to PluginClassAttribute
.Cast<PluginClassAttribute>()
// return the PluginType property from each PluginClassAttribute instance
.Select(a => a.PluginType)
).ToList();
Lambda表达式与代表
让我们完成这个关闭的lambda表达式比较代表。看看下面的清单:
List<string> strings = new List<string> { "one", "two", "three" };
说,我们要过滤掉那些以字母“T”开头:
var result = strings.Where(s => s.StartsWith("t"));
这是最常用的方法;使用lambda表达式进行设置。但也有备选方案:
Func<string,bool> func = delegate(string s) { return s.StartsWith("t");};
result = strings.Where(func);
这基本上是同一件事:第一,我们创建类型Func<string, bool>
的委托(这意味着它需要一个string
作为输入参数,并返回一个bool
)。然后我们将该委托作为参数传递给Where
方法。这是编译器在第一个示例的幕后(strings.Where(s => s.StartsWith("t"));
)为我们做的。
三分之一选择是简单地委托传递给非匿名方法:
private bool StringsStartingWithT(string s)
{
return s.StartsWith("t");
}
// somewhere else in the code:
result = strings.Where(StringsStartingWithT);
所以,我们正在寻找在这里的情况,lambda表达式是定义一个相当简洁的方式委托,通常指的是匿名方法。
如果你有能读到这里所有的方式,好了,感谢您的时间:)
基本上,lambda表达式是像任何其他功能除了它们被定义,无论你需要他们。你熟悉匿名课程吗?他们只是为了方法而已。 (作为评论张贴,因为我不能希望接近其他答案的质量) – RCIX 2010-01-30 09:42:09
我将无耻地插入一个乔恩Skeet参考:http://csharpindepth.com/Articles/Chapter5/Closures.aspx这实际上帮助增加了我对lambda表达式的理解。非常好的阅读,当然! – IAbstract 2010-02-08 22:53:48
我强烈建议您访问Lambdaexpression.net – Delashmate 2011-09-16 09:33:22