Lambda运算符如何工作以及它如何简化LINQ(c#)中的表达式?

时间:2013-10-21 09:09:39

标签: c# linq expression

我是C#学习的新手,我无法清楚地了解lambda运算符,但我理解的是它简化了表达式。

 var testString = Console.ReadLine();
            testString.ToCharArray()
            .OrderBy(i => i).ToLookup(j => j)
            .Select(i => new Program { letter = i.Key, count = i.Count() }).ToList()
            .ForEach(i => Console.WriteLine("letter {0},count {1}", i.letter, i.count,i.sign));

在上面的代码中,我没有得到'我'和'j'。是匿名类型的变量或对象吗?

1 个答案:

答案 0 :(得分:2)

问题在于你的问题本身是错误的,你会问“这是一个变量或对象还是匿名类型”,好像这3个东西是不相容的。匿名类型具有实例,它们是对象,您引用这些对象的名称是变量。我会尝试澄清语法,以便它对你更有意义。

要了解发生了什么,你必须看看所有那些花哨的linq运营商作为签名,让我们以OrderBy为例:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);

第一个参数是您调用orderby的对象(如果这让您感到困惑,Google up extention方法),另一个参数(对应于代码中的i =&gt; i)是:< / p>

Func<TSource, TKey> keySelector

现在我们需要深入挖掘并看看“Func”是什么,让我们来看看Func的定义:

public delegate TResult Func<in T, out TResult>(T arg)

Func是。 。 。代表定义!在引入lambda之前已经存在的东西,现在我们知道了什么是i =&gt;我是Wise类型,我们可以尝试理解我是什么,为此我们需要剖析语法。我们知道i =&gt;我是一个委托功能,一旦我们推断出类型(通过知道你的可枚举的类型),它的签名就像这样,无论是在&amp;在调用orderby之后,你正在处理一个可枚举的char,所以i =&gt;我是一个Func,它是一个委托char Func(char Item),基本上是一个接受char的委托,并返回一个char。 / p>

Lambda函数是在非常特定的场景中表达委托的一种非常简洁的方式,让我们来看看你可以做到的旧方法

char MyMethod(char c)
{
    return c;
}

bla.OrderBy(MyMethod); // This is a very verbose version, we defined an external method

现在,在您使用委托时,这种方式很有意义,因为您必须指定所有这些信息(在非通用情况下,您无法使用类型推断)。然而正如我之前所说,我们知道(感谢推断)你从一开始就在使用Func,这要归功于你所调用的对象的类型,这意味着我们可以删除冗余信息并最终用:

MyMethod(c)
{
   return c;
}

我们还能剥夺什么?那个方法的名字!为什么?因为我们只使用过一次所以如果它不会被重复使用,为什么要命名呢!

(c){return c;}

此外,你经常想要做一个非常简单的事情,在一个语句中保存,所以为什么要麻烦地返回它,让我们只是隐含地返回语句解析的内容并删除括号!    (c)c

现在我们留下了与原始代码完全相同的东西(原始代码中的所有其他代码都是无用的,可以从我演示的上下文中获取)所以我们只需更改语法来实现它通过添加lambda运算符明显不同=&gt;在输入变量和代码之间

(C)=&以及c

如果您只通过删除()

传递单个元素,则可以再次简化

C =&以及c

那么什么是lambda运算符?它是签名和代码之间的分隔符,整个表达式声明了一个while方法而没有命名它,并且让编译器尽可能地推断它,内联在哪里迭代以非常简洁的语法使用它。在你的情况下,我是一个局部变量,作为你内联定义的委托的输入传入。

对于你的示例中没有使用任何匿名类型的匿名类型,它们是内联声明但未命名的类型,并且也意味着在查询范围内使用(就像lambda表达式避免创建一样)对于您不需要命名且不会重复使用的代码的一次性函数,匿名类型避免为您只使用一次的数据创建1个镜头类。