Мне нравится ответ Дэвида, но я думал, что буду педантичным. Вопрос говорит: «После того, как он скомпилирован» - это говорит о том, что оба выражения имеют скомпилировано. Как они оба могут скомпилироваться, но если один преобразовать в делегат, а другой в дерево выражений? Это сложно - вам нужно использовать другую функцию анонимных методов; единственный, который не разделяется лямбда-выражениями. Если вы указываете анонимный метод без указания списка параметров для всех , он совместим с любым типом делегата, возвращающим 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; } );
}
}
Уч. Помните, дети, каждый раз, когда вы перегружаете метод, унаследованный от базового класса, маленький котенок начинает плакать.