讓我們來分析您的代碼示例:
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