请参阅下面Go()方法中的四行:
delegate void Action<T>(T arg);
delegate void Action();
void DoSomething<T>(Action<T> action)
{
//...
}
void DoSomething(Action action)
{
//...
}
void MyAction<T>(T arg)
{
//...
}
void MyAction()
{
//...
}
void Go<T>()
{
DoSomething<T>(MyAction<T>); // throws compiler error - why?
DoSomething(new Action<T>(MyAction<T>)); // no problems here
DoSomething(MyAction); // what's the difference between this...
DoSomething(new Action(MyAction)); // ... and this?
}
请注意,第一次调用生成的编译器错误是: 方法'Action(T)'的类型参数无法从用法中推断出来。尝试明确指定类型参数。
答案 0 :(得分:14)
MyAction
和new Action(MyAction)
之间没有区别(当它们都有效时),除了前者在C#1中不起作用。这是implicit method group conversion
。有些时候这是不适用的,最值得注意的是当编译器无法确定你想要什么类型的委托时,例如。
Delegate foo = new Action(MyAction); // Fine
Delegate bar = MyAction; // Nope, can't tell target type
这在您的问题中发挥作用,因为所涉及的两种方法都被重载了。这基本上导致了头痛。
至于仿制药方面 - 这很有意思。方法组并没有从C#3类型推断中得到太多的喜爱 - 我不确定它是否会在C#4中得到改进。如果你调用泛型方法并指定类型参数,那么类型推理工作得相当好 - 但是如果你试图以相反的方式进行,它就会失败:
using System;
class Test
{
static void Main()
{
// Valid - it infers Foo<int>
DoSomething<int>(Foo);
// Valid - both are specified
DoSomething<int>(Foo<int>);
// Invalid - type inference fails
DoSomething(Foo<int>);
// Invalid - mismatched types, basically
DoSomething<int>(Foo<string>);
}
static void Foo<T>(T input)
{
}
static void DoSomething<T>(Action<T> action)
{
Console.WriteLine(typeof(T));
}
}
C#3中的类型推断非常复杂,并且在大多数情况下运行良好(特别是它对LINQ很有用)但在其他一些情况下失败。在理想的世界中,在未来版本中理解和会变得更加容易......我们会看到!
答案 1 :(得分:3)
非泛型隐式委托创建只是语法糖,因此编译器为
生成完全相同的代码DoSomething(MyAction);
和
DoSomething(new Action(MyAction));
因为它可以直接从方法参数&amp;中推断出委托的类型。上下文。
使用泛型委托,由于协方差和逆变而必须指定委托类型(详见http://msdn.microsoft.com/en-us/library/ms173174(VS.80).aspx) - T in Action可以是方法中T的超类型,它仍然是被接受为代表方法。因此,您需要在委托中明确指定T,因为编译器无法自行解决它。
答案 2 :(得分:1)
只是一个旁注.. 出于某种原因,这适用于VB。
当我将Methodgroup / adderessof转换为委托时,似乎C#中的预处理器的实现和VB不同。