C# 3.0
可枚举。其中循环列表并创建一个新列表,该列表仅包含所提供函数返回true的元素。这样,您就不用编写代码来遍历列表、检查每个元素的谓词并执行某些操作。我了解lambdas基础知识的技巧有两个方面 首先,我建议学习函数式编程。在这方面,Haskell是一种很好的语言。我正在使用的这本书是格雷厄姆·赫顿写的,从中受益匪浅。这为Haskell打下了良好的基础,包括对lambdas的解释 从这里开始,我认为您应该看到,他们也对函数式编程进行了很好的介绍,还使用了Haskell,并过渡到了CC# 3.0 ,c#-3.0,lambda,C# 3.0,Lambda,可枚举。其中循环列表并创建一个新列表,该列表仅包含所提供函数返回true的元素。这样,您就不用编写代码来遍历列表、检查每个元素的谓词并执行某些操作。我了解lambdas基础知识的技巧有两个方面 首先,我建议学习函数式编程。在这方面,Haskell是一种很好的语言。我正在使用的这本书是格雷厄姆·赫顿写的,从中受益匪浅。这为Haskell打下了良好的基础,包括对lambdas的解释 从这里开始,我认为您应该看到,他们也对函数式编程进行了很好的介绍,还使用了Haskell,并过渡到了C 一旦您了解了所
一旦您了解了所有这些,您就应该能够很好地理解lambdas了。让我们剖析一下您的代码示例:
filenames.SelectMany(f =>
Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
.Cast<PluginClassAttribute>()
.Select(a => a.PluginType)
).ToList();
SelectMany
将委托作为参数,在这种情况下,委托必须将类型为string
的一个参数作为输入,并返回IEnumerable
(其中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
上,将调用Cast()
,返回一个IEnumerable
现在我们有了一个IEnumerable
,我们在上面调用Select
。Select
方法类似于SelectMany
,但返回类型为T
(由编译器推断)的单个实例,而不是IEnumerable
。设置相同;对于IEnumerable
中的每个元素,它将调用已定义的委托,并将当前元素值传递给它:
.Select(a => a.PluginType)
同样,a
是输入参数,a.PluginType
是方法主体。因此,对于列表中的每个PluginClassAttribute
实例,它将返回PluginType
属性的值(我将假定此属性属于类型
)
执行摘要如果我们把这些碎片粘在一起:
// 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表达式设置它。但也有其他选择:
Func<string,bool> func = delegate(string s) { return s.StartsWith("t");};
result = strings.Where(func);
因此,在我们这里看到的例子中,lambda表达式是定义委托的一种相当紧凑的方式,通常引用匿名方法
如果你有足够的精力在这里阅读,那么,谢谢你的时间:)一个很好的简单解释是,TekPub上的这个简单的视频,针对那些对编码非常熟悉但对lambdas不熟悉的开发人员
显然,这里有很多反馈,但这是另一个很好的来源和简单的解释。CodeProject最近有一篇很好的介绍性文章:我知道这有点老了,但我来这里是为了理解所有这些lambda的东西。 当我把所有的答案和评论都翻了一遍之后,我对lambda有了更好的理解,我想我应该添加这个简单的答案(从学习者的角度来看): 不要混淆
a=>a+1
的意思是将1添加到a并将结果返回到a。(这很可能是初学者困惑的根源。
而是这样看:a是函数的输入参数(未命名函数),a+1是函数中的语句(未命名函数“动态构造”)
希望这有帮助:)基本上,lambda与任何其他函数都一样,只是它们是在需要的地方定义的。你熟悉匿名类吗?他们这样做只是为了方法。(作为评论发布,因为我不希望达到其他答案的质量)我将无耻地插入Jon Skeet的引用:这实际上有助于提高我对lambda表达式的理解。很好的阅读,当然!!!我强烈建议您访问Lambdaexpression.net只是随机地重新访问一下。。。如果您现在还没有弄明白这一点-您不需要在您发布的lambda中进行“==true”检查。它可以简单地通过执行“start=>start.IsBatch”来表示,因为IsBatch本身是一个布尔值。@kastermester:当然,今天我会用不同的方式来写;)。。。我很高兴看到这个问题和出色的答案帮助了很多人。@Fredrik mörk:非常好的解释,感谢你在“图解”陈述中的帮助。当你不懂速记版本的时候,这是很吓人的。在你和Kastermester之间,我想我得到了这个…这不是火车!!!再次感谢你!这是对我们其他人似乎忽视的一个实际问题的一个很好的回答——干得好!好极了这正是我需要的解释。谢谢你花时间写这篇文章@卡斯特:谢谢你的解释。我想有一件事让我感到不舒服,那就是推断出的参数“类型”。干得好!!不客气,很高兴我能帮上忙。在C#代码中最初几次遇到它们时,很难理解它们——一旦你理解了,它们可以让很多东西变得更简单——而且它们非常有用,不仅仅是与LINQ.+1个漂亮的视频剪辑结合使用……我的声音坏了:(我得到了
private int sum5(int n)
{
return n + 5;
}
...methodbody
int acc = 5;
Func<int> addAcc = (n) => n + acc;
IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);
string MyConcat(string str){
return str + str;
}
...
void myMethod(){
IEnumerable<string> result = someIEnumerable.Select(MyConcat);
}
void myMethod(){
IEnumerable<string> result = someIEnumerable.Select(s => s + s);
}
void myMethod(){
IEnumerable<string> result = someIEnumerable.Select((string s) => s + s);
}
a => a + 1
List<string> fruits = new List<string> {
"apple", "passionfruit", "banana", "mango",
"orange", "blueberry", "grape", "strawberry" };
IEnumerable<string> shortFruits = fruits.Where(fruit => fruit.Length < 6);
foreach (string fruit in shortFruits) {
Console.WriteLine(fruit);
}
filenames.SelectMany(f =>
Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
.Cast<PluginClassAttribute>()
.Select(a => a.PluginType)
).ToList();
filenames.SelectMany(
...
).ToList();
filenames.SelectMany(f =>
Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
).ToList()
.Select(a => a.PluginType)
// 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();
List<string> strings = new List<string> { "one", "two", "three" };
var result = strings.Where(s => s.StartsWith("t"));
Func<string,bool> func = delegate(string s) { return s.StartsWith("t");};
result = strings.Where(func);
private bool StringsStartingWithT(string s)
{
return s.StartsWith("t");
}
// somewhere else in the code:
result = strings.Where(StringsStartingWithT);