3

我想,对于熟悉 lambda 的人来说,这是一个非常简单的问题。我刚刚学习它并且遇到了一种对我来说没有意义的表达方式。

据我了解,lambda 表达式传入左侧指定的变量并运行右侧的代码。例如

myFunction = x => x + x;

所以 myFunction(2) 会返回 4。

无论如何,我在这里查看了一个 linq 查询并看到了这个:

IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);

……那n => n有什么用?为什么不直接说OrderBy(n)?你所做的就是将 n 传递给一个只返回的函数n。>_> 这里发生了什么?

4

3 回答 3

9

……那n => n有什么用?

它只是将任何值映射到自身。这是一个身份功能。

为什么不直接说 OrderBy(n)?

因为n它不是范围内的变量——这样调用它是无效的。这不是一个 lambda 表达式,所以它只会尝试n用作普通的方法参数。

您的代码只是想说“按每个元素的整个顺序排列此序列”,而不是将每个元素投影到其他值,但没有办法直接这么说。

OrderBy 需要从元素类型到排序键类型的投影——只是在这种情况下我们需要标识投影。

您可以编写自己的额外扩展方法:

public static IEnumerable<T> OrderNaturally<T>(this IEnumerable<T> source)
{
    return source.OrderBy(item => item);
}

然后将您的原始声明更改为:

IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderNaturally();

如果您发现它更具可读性。

或者,您可以创建一个Functions包含一些有用的静态只读字段的类:

public static class Functions<T>
{
    public static readonly Func<T, T> Identity = x => x;
    public static readonly Func<T, T> DefaultValue => x => default(T);
    public static readonly Func<T, string> ToString = x => x == null ? null : x.ToString();
    ...
}

然后:

IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0)
                                    .OrderBy(Functions<int>.Identity)

我不认为我那样做......我只是在建议要考虑的事情:)

于 2013-05-30T17:55:28.107 回答
4

让我们分解一下:

numbers

这是一个集合integers

.Where(num => num % 2 == 0)

这就是说“在我的集合中找到我的数字模数 2 = 0 的所有项目”。

.OrderBy(n => n);

然后这是对列表的排序。因为列表是整数,并且指定的项目是整数,所以它将按数字顺序排列,从低到高。

您需要的原因n => n是因为您可以按价值以外的东西进行排序。例如,将项目的长度作为字符串

.OrderBy(n => n.ToString().Length)

显然,对于整数,这没有任何意义。但是对于其他数据类型,比如类,这非常有用。

于 2013-05-30T17:56:58.653 回答
0

n => n表示该函数接受一个参数作为输入并将其作为返回值返回。

为什么不直接说OrderBy(n)

你怎么知道这n是一个 lambda?有什么迹象表明它是一个功能?如果你有一个名为 的函数,n它接受一个整数并返回相同的整数,那么你可以这样做,但我猜这不是你想要的。

我知道你没有问,但是:

C# 编译器团队是否可以使用一些替代语法来涵盖“identity lambda”的特殊情况?

(“identity lambda”是只返回一个输入值的函数的技术术语)。

是的。他们本来可以的。他们没有,可能是因为他们认为不值得花时间/精力,因为编写一个恒等函数很容易,不需要任何特殊语法。

于 2013-05-30T17:56:56.390 回答