我最近搬到了.net 3.0(Windows窗体,C#)。我想更多地了解谓词和lambda表达式。我们应该在哪里使用它们?他们是否提高了表现?以及他们如何在内部工作。感谢。
答案 0 :(得分:5)
如果你搜索Stack Overflow,你会发现大约一千个答案,解释它们的用途。简而言之 - lambda是一种在您希望将其传递给另一个方法的位置编写匿名方法的方法。技术上与匿名方法的delegate
语法相同,但具有类型推断的附加功能,因此您无需声明参数类型。谓词是一种接受某个值并返回bool
的方法 - 一个例子是Where
的参数。
不引用任何外部变量的lambda将变为具有虚构名称的私有静态方法。如果它引用封闭类的实例成员,它将成为实例方法。如果它引用局部变量,那些变量将被“提升”为编译器生成的类的字段,该类在封闭方法开始运行时分配,并且lambda的主体成为该新类中的方法。
至于表现,他们并没有那么大的差别。它们涉及创建临时对象,但I find that these are collected extremely efficiently by the GC。
答案 1 :(得分:1)
如果你想研究不同版本的C#以及它们的不同之处。我的建议是阅读jon skeet的书S.Sharp.in.Depth。这将使您更好地理解新版本
答案 2 :(得分:0)
他们是否提高了表现?如何 他们在内部工作吗感谢。
在大多数情况下,你永远不会注意到性能的提升。然而,有一些病态案例会扼杀性能,即过度使用fixed point combinators。
这是一个众所周知的技巧,我们可以使用Y-combinator编写递归的lambda函数,但请考虑以下代码:
using System;
using System.Diagnostics;
namespace YCombinator
{
class Program
{
static Func<T, U> y<T, U>(Func<Func<T, U>, Func<T, U>> f)
{
return f(x => y<T, U>(f)(x));
}
static int fibIter(int n)
{
int fib0 = 0, fib1 = 1;
for (int i = 1; i <= n; i++)
{
int tmp = fib0;
fib0 = fib1;
fib1 = tmp + fib1;
}
return fib0;
}
static Func<int, int> fibCombinator()
{
return y<int, int>(f => n =>
{
switch (n)
{
case 0: return 0;
case 1: return 1;
default: return f(n - 1) + f(n - 2);
}
});
}
static int fibRecursive(int n)
{
switch (n)
{
case 0: return 0;
case 1: return 1;
default: return fibRecursive(n - 1) + fibRecursive(n - 2);
}
}
static void Benchmark(string msg, int iterations, Func<int, int> f)
{
int[] testCases = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20 };
Stopwatch watch = Stopwatch.StartNew();
for (int i = 0; i <= iterations; i++)
{
foreach (int n in testCases)
{
f(n);
}
}
watch.Stop();
Console.WriteLine("{0}: {1}", msg, watch.Elapsed.TotalMilliseconds);
}
static void Main(string[] args)
{
int iterations = 10000;
Benchmark("fibIter", iterations, fibIter);
Benchmark("fibCombinator", iterations, fibCombinator());
Benchmark("fibRecursive", iterations, fibRecursive);
Console.ReadKey(true);
}
}
}
此程序打印出来:
fibIter: 14.8074 fibCombinator: 61775.1485 fibRecursive: 2591.2444
fibCombinator和fibRecursive在功能上是等效的,具有相同的计算复杂度,但由于所有的中间对象分配,fibCombinator的速度要快4100倍。