谓词和lambda表达式

时间:2009-08-03 17:31:29

标签: c# lambda predicate

我最近搬到了.net 3.0(Windows窗体,C#)。我想更多地了解谓词和lambda表达式。我们应该在哪里使用它们?他们是否提高了表现?以及他们如何在内部工作。感谢。

3 个答案:

答案 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倍。