Lambda for Dummies ....任何人,有人吗?我觉得不是 [英] Lambda for Dummies....anyone, anyone? I think not

查看:68
本文介绍了Lambda for Dummies ....任何人,有人吗?我觉得不是的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在寻求了解看起来很奇怪的'=>'运算符时,我发现了一个不错的开始的地方,作者非常简洁明了:


 参数=>表达式


有人在理解lambda的基础上有任何提示吗?



例如:如果我得到类似的信息(来自在这里收到的答案):

  filenames.SelectMany(f => 
Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute),true)
.Cast< PluginClassAttribute>()
.Select(a => a.PluginType)
).ToList();

如何将其分解为更简单的部分?






更新:想炫耀我的第一个lambda表达式。不要嘲笑我,但是我没有复制别人的例子就这样做了……而且它第一次起作用:

  public ModuleData [] GetStartModules()
{返回modules.FindAll(start => start.IsBatch == true).ToArray(); }


解决方案

我们来剖析您的代码示例:

 文件名.SelectMany(f => 
Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute),true)
.Cast< PluginClassAttribute>()
.Select(a => a.PluginType)
).ToList();

因此,我们从 string [] 称为文件名。我们在数组上调用 SelectMany 扩展方法,然后在结果上调用 ToList

 文件名.SelectMany(
...
).ToList();

SelectMany 以委托作为参数,在在这种情况下,委托人必须采用类型为 string 的一个参数作为输入,并返回 IEnumerable< T> (其中推断出 T 的类型)。这是lambda进入阶段的地方:

 文件名.SelectMany(f => 
Assembly.LoadFrom(f) .GetCustomAttributes(typeof(PluginClassAttribute),true)
).ToList()

将会这是因为对于文件名数组中的每个元素,都会调用委托。 f 是输入参数, => 右边的内容是委托引用的方法主体至。在这种情况下,将为数组中的文件名调用 Assembly.LoadFrom ,使用以下命令将文件名传递给 LoadFrom 方法 f 参数。在返回的 AssemblyInstance 上,将调用 GetCustomAttributes(typeof(PluginClassAttribute),true),它返回一个数组 Attribute 实例的数量。因此,编译器无法推断前面提到的 T 的类型是 Assembly



在返回的 IEnumerable< Attribute< 上, Cast< PluginClassAttribute>()被调用,返回 IEnumerable< PluginClassAttribute>



所以我们现在有了 IEnumerable< ; PluginClassAttribute> ,然后在其上调用 Select Select 方法类似于 SelectMany ,但是返回单个类型为 T 的实例。 code>(由编译器推断),而不是 IEnumerable< T> 。设置是相同的;对于 IEnumerable< PluginClassAttribute> 中的每个元素,它将调用已定义的委托,并将当前元素值传递给它:

  .Select(a => a.PluginType)



a
是输入参数, a.PluginType 是方法主体。因此,对于列表中的每个 PluginClassAttribute 实例,它将返回 PluginType 属性的值(我假设属性的类型为 Type )。



执行摘要

如果我们将那些零碎的部分粘合在一起:

  //处理文件名数组
文件名中的所有字符串。 SelectMany(f =>
//从具有给定文件名
//的程序集
//中获取类型为PluginClassAttribute的所有Attributes。 ,true)
//将返回的实例转换为PluginClassAttribute
.Cast< PluginClassAttribute>()
//从每个PluginClassAttribute实例
中返回PluginType属性.Select(a => ; a.PluginType)
).ToList();






Lambdas与代理人

让我们通过比较lambda和委托来完成这一点。采取以下列表:

  List< string>字符串=新列表< string> { 一二三 }; 

说我们要过滤掉以字母 t开头的内容:

  var result = strings.Where(s => s.StartsWith( t)); 

这是最常见的方法;使用lambda表达式进行设置。但是还有其他选择:

  Func< string,bool> func = proxy(string s){return s.StartsWith( t);}; 
结果=字符串。

这基本上是相同的:首先,我们创建一个类型为的委托Func< string,bool> (这意味着它将 string 作为输入参数,并返回 bool )。然后,将该委托作为参数传递给 Where 方法。这是编译器在第一个示例( strings.Where(s => s.StartsWith( t)); )的幕后为我们做的。 / p>

第三种选择是简单地将委托传递给非匿名方法:

  private bool StringsStartingWithT(string s)
{
return s.StartsWith( t);
}

//代码中的其他地方:
result = strings.Where(StringsStartingWithT);

因此,在我们看这里的情况下,lambda表达式是一种相当紧凑的方法



如果您有足够的精力在这里读完,那么,谢谢您的时间:)


In my quest to understand the very odd looking ' => ' operator, I have found a good place to start, and the author is very concise and clear:

parameters => expression

Does anyone have any tips on understanding the basics of lambdas so that it becomes easier to 'decipher' the more complex lambda statements?

For instance: if I am given something like (from an answer I received here):

filenames.SelectMany(f => 
        Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
        .Cast<PluginClassAttribute>()
        .Select(a => a.PluginType)
).ToList();

How can I go about breaking this down into more simple pieces?


UPDATE: wanted to show off my first lambda expression. Don't laugh at me, but I did it without copying someone's example...and it worked the first time:

public ModuleData[] GetStartModules( )
{ return modules.FindAll(start => start.IsBatch == true).ToArray(); }

解决方案

Let's dissect your code sample:

filenames.SelectMany(f => 
        Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
        .Cast<PluginClassAttribute>()
        .Select(a => a.PluginType)
).ToList();

So, we start off with a string[] called filenames. We invoke the SelectMany extension method on the array, and then we invoke ToList on the result:

filenames.SelectMany(
   ...
).ToList();

SelectMany takes a delegate as parameter, in this case the delegate must take one parameter of the type string as input, and return an IEnumerable<T> (Where the type of T is inferred). This is where lambdas enter the stage:

filenames.SelectMany(f => 
        Assembly.LoadFrom(f).GetCustomAttributes(typeof(PluginClassAttribute), true)
).ToList()

What will happen here is that for each element in the filenames array, the delegate will be invoked. f is the input parameter, and whatever comes to the right of => is the method body that the delegate refers to. In this case, Assembly.LoadFrom will be invoked for filename in the array, passing he filename into the LoadFrom method using the f argument. On the AssemblyInstance that is returned, GetCustomAttributes(typeof(PluginClassAttribute), true) will be invoked, which returns an array of Attribute instances. So the compiler can not infer that the type of T mentioned earlier is Assembly.

On the IEnumerable<Attribute> that is returned, Cast<PluginClassAttribute>() will be invoked, returning an IEnumerable<PluginClassAttribute>.

So now we have an IEnumerable<PluginClassAttribute>, and we invoke Select on it. The Select method is similar to SelectMany, but returns a single instance of type T (which is inferred by the compiler) instead of an IEnumerable<T>. The setup is identical; for each element in the IEnumerable<PluginClassAttribute> it will invoke the defined delegate, passing the current element value into it:

.Select(a => a.PluginType)

Again, a is the input parameter, a.PluginType is the method body. So, for each PluginClassAttribute instance in the list, it will return the value of the PluginType property (I will assume this property is of the type Type).

Executive Summary
If we glue those bits and pieces together:

// 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();


Lambdas vs. Delegates
Let's finish this off by comparing lambdas to delegates. Take the following list:

List<string> strings = new List<string> { "one", "two", "three" };

Say we want to filter out those that starts with the letter "t":

var result = strings.Where(s => s.StartsWith("t"));

This is the most common approach; set it up using a lambda expression. But there are alternatives:

Func<string,bool> func = delegate(string s) { return s.StartsWith("t");};
result = strings.Where(func);

This is essentially the same thing: first we create a delegate of the type Func<string, bool> (that means that it takes a string as input parameter, and returns a bool). Then we pass that delegate as parameter to the Where method. This is what the compiler did for us behind the scenes in the first sample (strings.Where(s => s.StartsWith("t"));).

One third option is to simply pass a delegate to a non-anonymous method:

private bool StringsStartingWithT(string s)
{
    return s.StartsWith("t");
}

// somewhere else in the code:
result = strings.Where(StringsStartingWithT);

So, in the case that we are looking at here, the lambda expression is a rather compact way of defining a delegate, typically referring an anonymous method.

And if you had the energy read all the way here, well, thanks for your time :)

这篇关于Lambda for Dummies ....任何人,有人吗?我觉得不是的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆