Вопрос

После компиляции есть ли разница между:

delegate { x = 0; }

и

() => { x = 0 }

?

Это было полезно?

Решение

Короткий ответ :нет.

Более длинный ответ, который может быть неактуален:

  • Если вы назначаете лямбду типу делегата (например, Func или Action) вы получите анонимного делегата.
  • Если вы присвоите лямбду типу выражения, вы получите дерево выражений вместо анонимного делегата.Затем дерево выражений можно скомпилировать в анонимный делегат.

Редактировать:Вот несколько ссылок на выражения.

  • System.Linq.Expression.Expression(TDelegate) (Начни здесь).
  • Linq в памяти с делегатами (например, System.Func) использует System.Linq.Enumerable.Linq to SQL (и все остальное) с выражениями использует System.Linq.Queryable.Проверьте параметры этих методов.
  • Ан Объяснение от ScottGu.Короче говоря, Linq в памяти создаст несколько анонимных методов для решения вашего запроса.Linq to SQL создаст дерево выражений, представляющее запрос, а затем преобразует это дерево в T-SQL.Linq to Entities создаст дерево выражений, представляющее запрос, а затем преобразует это дерево в соответствующий платформе SQL.

Другие советы

Мне нравится ответ Дэвида, но я думал, что буду педантичен.В вопросе говорится: «Как только он будет скомпилирован», что предполагает, что оба выражения иметь был составлен.Как они могли скомпилироваться, но один из них был преобразован в делегат, а другой в дерево выражений?Это непростая задача — вам придется использовать еще одну особенность анонимных методов;единственный, который не используется лямбда-выражениями.Если вы укажете анонимный метод без указания списка параметров совсем он совместим с любым типом делегата, возвращающим void и без каких-либо out параметры.Вооружившись этими знаниями, мы сможем построить две перегрузки, чтобы сделать выражения совершенно однозначными, но очень разными.

Но случается беда!По крайней мере, в C# 3.0 вы не можете преобразовать лямбда-выражение с телом блока в выражение, а также не можете преобразовать лямбда-выражение с присваиванием в теле (даже если оно используется в качестве возвращаемого значения).Это может измениться с выходом C# 4.0 и .NET 4.0, которые позволяют больше выражать в дереве выражений.Другими словами, с примерами, которые привел MojoFilter, эти двое будут почти всегда конвертироваться в одно и то же.(Подробнее через минуту.)

Мы можем использовать трюк с параметрами делегата, если немного изменим тела:

using System;
using System.Linq.Expressions;

public class Test
{
    static void Main()
    {
        int x = 0;
        Foo( () => x );
        Foo( delegate { return x; } );
    }

    static void Foo(Func<int, int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }

    static void Foo(Expression<Func<int>> func)
    {
        Console.WriteLine("I suspect the lambda expression...");
    }
}

Но ждать!Если мы достаточно хитры, мы можем отличить их даже без использования деревьев выражений.В приведенном ниже примере используются правила разрешения перегрузки (и прием сопоставления анонимных делегатов)...

using System;
using System.Linq.Expressions;

public class Base
{
    public void Foo(Action action)
    {
        Console.WriteLine("I suspect the lambda expression...");
    }
}

public class Derived : Base
{
    public void Foo(Action<int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }
}

class Test
{
    static void Main()
    {
        Derived d = new Derived();
        int x = 0;
        d.Foo( () => { x = 0; } );
        d.Foo( delegate { x = 0; } );
    }
}

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

Дэвид Б. прав.Обратите внимание, что использование деревьев выражений может иметь преимущества.LINQ to SQL проверит дерево выражений и преобразует его в SQL.

Вы также можете поэкспериментировать с лямбдами и деревьями выражений, чтобы эффективно передавать имена членов класса в структуру безопасным для рефакторинга способом. Мокк является примером этого.

В двух приведенных выше примерах разницы нет, ноль.

Выражение:

() => { x = 0 }

— это лямбда-выражение с телом инструкции, поэтому его нельзя скомпилировать как дерево выражений.На самом деле он даже не компилируется, потому что после 0 нужна точка с запятой:

() => { x = 0; } // Lambda statement body
() => x = 0      // Lambda expression body, could be an expression tree. 

Есть разница

Пример:

var mytask = Task.Factory.StartNew(() =>
{
    Thread.Sleep(5000);
    return 2712;
});
mytask.ContinueWith(delegate
{
    _backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});   

И я заменяю лямбда: (ошибка)

var mytask = Task.Factory.StartNew(() =>
{
    Thread.Sleep(5000);
    return 2712;
});
mytask.ContinueWith(()=>
{
    _backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});

Некоторые основы здесь.

Это анонимный метод

(string testString) => { Console.WriteLine(testString); };

Поскольку анонимные методы не имеют имен, нам нужен делегат, которому мы можем назначить оба этих метода или выражения.например

delegate void PrintTestString(string testString); // declare a delegate

PrintTestString print = (string testString) => { Console.WriteLine(testString); }; 
print();

То же самое и с лямбда-выражением.Обычно нам нужен делегат, чтобы использовать их.

s => s.Age > someValue && s.Age < someValue    // will return true/false

Мы можем использовать делегат func для использования этого выражения.

Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;

bool result = checkStudentAge ( Student Object);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top