Как только он скомпилирован, существует ли разница между:
delegate { x = 0; }
и
() => { x = 0 }
?
Как только он скомпилирован, существует ли разница между:
delegate { x = 0; }
и
() => { x = 0 }
?
Короткий ответ: нет.
Более длинный ответ, который может быть неактуальным:
Func
или Action
), вы получите анонимный делегат.Изменить: Вот некоторые ссылки для выражений.
Мне нравится Дэвид, но я думал, что буду педантичным. В этом вопросе говорится: "Как только он скомпилирован" - это говорит о том, что оба выражения были скомпилированы. Как они могут скомпилировать, но с одним преобразованным в делегат, а другой - в дерево выражений? Это сложная задача - вам нужно использовать другую функцию анонимных методов; единственный, который не разделяется лямбда-выражениями. Если вы укажете анонимный метод без указания списка параметров, он будет совместим с любым типом делегата, возвращающим void и без каких-либо параметров out
. Вооружившись этими знаниями, мы должны иметь возможность построить две перегрузки, чтобы сделать выражения совершенно однозначными, но очень разными.
Но удары бедствия! По крайней мере, с С# 3.0 вы не можете преобразовать лямбда-выражение с блочным телом в выражение - и вы не можете преобразовать лямбда-выражение с назначением в тело (даже если оно используется как возвращаемое значение). Это может измениться с помощью С# 4.0 и .NET 4.0, которые позволяют больше выражать в дереве выражений. Таким образом, другими словами, с примерами, которые МоджоФилтер дал, они почти всегда будут преобразованы в одно и то же. (Подробнее в минуту.)
Мы можем использовать трюк параметров делегата, если немного изменить тела:
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; } );
}
}
Уч. Помните детей, каждый раз, когда вы перегружаете метод, унаследованный от базового класса, маленький котенок начинает плакать.
В двух приведенных выше примерах нет разницы, ноль.
Выражение:
() => { x = 0 }
- это выражение Lambda с телом оператора, поэтому оно не может быть скомпилировано как дерево выражений. На самом деле он даже не компилируется, потому что ему нужна точка с запятой после 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);