Olivier的答案基本上是正确的,但它可以使用一些额外的解释。
为什么反映静态工厂方法的返回类型给出具体类型,而调用构造函数内联给出接口?我希望他们两个是相同的
你Program类相当于下面的类:
class Program
{
static void Test(ThingCreator creator)
{
Console.WriteLine(creator.Method.ReturnType);
}
static IThing Anon1()
{
return new Foo();
}
static IThing Anon2()
{
return new Bar();
}
static void Main()
{
Test(new ThingCreator(Foo.Create));
Test(new ThingCreator(Bar.Create));
Test(new ThingCreator(Program.Anon1));
Test(new ThingCreator(Program.Anon2));
}
}
现在应该很清楚为什么程序打印它做什么。
这里的故事的寓意是,当我们产生了lambda表达式的隐藏方法,这些隐藏的方法返回任何被要求委托,而不是无论拉姆达返回。
这是为什么?
更密切的例子就是证明:
static void Blah(Func<object> f)
{
Console.WriteLine(f().ToString());
}
static void Main()
{
Blah(() => 123);
}
我希望你同意,这必须作为
static object Anon() { return (object)123; }
中产生,而不是
static int Anon() { return 123; }
因为后者不能转换为Func<object>
!拳击指令无处可去,但ToString
的呼叫期望f()
返回参考类型。
因此,一般规则是,当作为隐藏方法引用时,lambda必须具有通过转换为委托类型授予的返回类型。
此外,有没有办法在lambda版本中指定我想返回值是具体类型?或者是调用静态方法来做到这一点?
当然。
interface IThing {}
class Foo : IThing {}
delegate T ThingCreator<T>() where T : IThing;
public class Program
{
static void Test<T>(ThingCreator<T> tc) where T : IThing
{
Console.WriteLine(tc.Method.ReturnType);
}
public static void Main()
{
Test(() => new Foo());
}
}
这是为什么不同?
由于类型推断推断T
是Foo
,因此我们正在转换的lambda来ThingCreator<Foo>
,其具有返回类型Foo
。因此,生成的方法返回Foo
,因为委托类型需要。
别急,你说......我不能改变测试的签名或ThingCreator
无后顾之忧!您仍然可以使这项工作:
delegate T ThingCreator<T>() where T : IThing;
delegate IThing ThingCreator();
public class Program
{
static void Test(ThingCreator tc)
{
Console.WriteLine(tc.Method.ReturnType);
}
static ThingCreator DoIt<T>(ThingCreator<T> tc) where T : class, IThing
{
return tc.Invoke;
}
public static void Main()
{
Test(DoIt(() => new Foo()));
}
}
不利的一面是,现在你的非通用ThingCreator
代表每一个是调用ThingCreator<T>
代表,这是一个有点的时间和浪费内存的委托。但是,您得到了类型推断,方法组转换和lambda转换,使您成为所需返回类型的方法,并为该方法提供委托。
注意class
约束。你明白为什么约束必须在那里吗?这是作为练习给读者的。
__static__方法不是唯一的方法。你也可以使用非静态的。例如'Func f =()=> new Foo();测试(f.Invoke);'但真正的问题是,为什么你甚至检查(可能是多播)委托实例上的'.Method.ReturnType'?这有什么用处;你为什么在乎? –
@Jeppe - 第三方库有一个公共API,其方法类似于'Test'。我没有想到通过传递一个lambda而不是一个实际函数的引用的副作用。必须挖掘才能发现他们检查了方法的返回类型。如果它是我自己的代码,我不会创建这样的事情。 –