Как только он скомпилирован, есть ли разница между:
delegate { x = 0; }
и
() => { x = 0 }
?
Как только он скомпилирован, есть ли разница между:
delegate { x = 0; }
и
() => { x = 0 }
?
Ответы:
Краткий ответ: нет.
Более длинный ответ, который может быть не актуален:
Func
или Action
), вы получите анонимный делегат.Изменить: Вот несколько ссылок для выражений.
Мне нравится ответ Эми, но я думал, что буду педантичным. Вопрос говорит: «После того, как он составлен» - что говорит о том , что оба выражения было скомпилированы. Как они оба могут скомпилироваться, но с одним преобразованным в делегат, а другим в дерево выражений? Это сложный вопрос - вы должны использовать другую функцию анонимных методов; единственный, который не разделяется лямбда-выражениями. Если указать анонимный метод без указания списка параметров на все он совместит с любым типом делегата возвращения недействительным и без каких - либо 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; } );
}
}
Уч. Помните, дети, каждый раз, когда вы перегружаете метод, унаследованный от базового класса, маленький котенок начинает плакать.
delegate { ... }
это не то же самое, delegate() { ... }
что последний совместим только с типом делегата без параметров.
В двух приведенных выше примерах нет разницы, ноль.
Выражение:
() => { x = 0 }
является лямбда-выражением с телом оператора, поэтому его нельзя скомпилировать как дерево выражений. На самом деле он даже не компилируется, потому что ему нужно точка с запятой после 0:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Эми Б правильно. Обратите внимание, что могут быть преимущества использования деревьев выражений. LINQ to SQL проверит дерево выражений и преобразует его в SQL.
Вы также можете поиграть с лямдами и деревьями выражений, чтобы эффективно передавать имена членов класса в среду безопасным для рефакторинга способом. Moq является примером этого.
Есть разница
Пример:
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);