Предикаты и лямбда-выражения - PullRequest
0 голосов
/ 03 августа 2009

Я недавно перешел на .net 3.0 (формы Windows, C #). Я хочу узнать больше о предикатах и ​​лямбда-выражениях. Где мы должны их использовать? Улучшают ли они производительность? и как они работают внутри. Спасибо.

Ответы [ 3 ]

5 голосов
/ 03 августа 2009

При поиске переполнения стека вы найдете около тысячи ответов, объясняющих, для чего они нужны. Короче говоря, лямбда - это способ написания анонимного метода в том месте, где вы хотите передать его другому методу. Технически такой же, как синтаксис delegate для анонимного метода, хотя с добавленными полномочиями вывода типов, поэтому вам не нужно указывать типы параметров. Предикат - это метод, который принимает некоторое значение и возвращает bool - примером может служить аргумент Where.

Лямбда, которая не ссылается ни на какие внешние переменные, превращается в закрытый статический метод с выдуманным именем. Если он ссылается на члены экземпляра включающего класса, он становится методом экземпляра. Если он ссылается на локальные переменные, эти переменные «превращаются» в поля сгенерированного компилятором класса, который выделяется, когда запускается включающий метод, и тело лямбды становится методом в этом новом классе.

Что касается производительности, они не имеют большого значения. Они включают создание временных объектов, но Я считаю, что они чрезвычайно эффективно собираются GC .

1 голос
/ 03 августа 2009

Если вы хотите изучить различные версии C # и то, как они отличаются. Мой совет - прочитайте книгу C.Sharp.in. Это даст вам лучшее понимание новых версий

0 голосов
/ 03 августа 2009

Улучшают ли они производительность? и как они работают изнутри. Благодаря.

По большей части вы никогда не заметите снижение производительности. Однако есть некоторые патологические случаи, которые снижают производительность, а именно чрезмерное использование комбинаторов с фиксированной точкой .

Это хорошо известный трюк, который мы можем использовать Y-комбинатором для написания рекурсивных лямбда-функций, однако рассмотрим следующий код:

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 раз медленнее из-за всех распределений промежуточных объектов.

...