0

我是 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));

在上面的代码中,我没有得到关于“i”和“j”的信息。那是匿名类型的变量或对象吗?

4

1 回答 1

2

问题是你的问题本身是错误的,你问“是变量、对象还是匿名类型”,就好像这三件事不兼容一样。匿名类型有实例,它们是对象,引用这些对象的名称是变量。但是,我将尝试澄清语法,以便它对您更有意义。

要了解发生了什么,您必须查看所有那些花哨的 linq 运算符作为签名的内容,让我们以 OrderBy 为例:

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

第一个参数是您调用 orderby 的对象(如果这让您感到困惑,请使用 Google up 扩展方法),另一个参数(对应于代码中 i=>i 的参数)是这样的:

Func<TSource, TKey> keySelector

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

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

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

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){ 返回 c;}

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

现在我们留下了与原始代码完全相同的东西(原始代码中的所有附加代码都是无用的,可以从我演示的上下文中推断出来)所以我们只需更改语法以使其明显不同在输入变量和代码之间添加 lambda 运算符 =>

(c)=>c

如果您只通过删除 () 传入单个元素,则可以再次简化

c=>c

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

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

于 2013-10-22T16:58:33.007 回答