正如我在这里和那里读到的那样,new在C#中添加或删除调用列表中的方法(有或没有委托对象的关键字)是完全相同的,并产生相同的IL.例如,请参阅此示例:在C#中使用委托的两种方式(使用new关键字和不使用)具有此代码片段有什么区别:
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += this.button1_Click;
Run Code Online (Sandbox Code Playgroud)
这两者之间没有区别.但是当我用作delegate传递方法参数时,我意外地遇到了使用此代码观察异常输出:
private delegate void TextPrinter(string text);
private static TextPrinter _handler;
static void Main(string[] args)
{
TextPrinter myPrinter = PushMessage;
RegisterHandler(PushMessage);
UnRegisterHandler(PushMessage);
InvokePrinter("hello");
}
private static void RegisterHandler(TextPrinter methods)
{
_handler += methods;
}
private static void UnRegisterHandler(TextPrinter methods)
{
/* first routine >> */_handler -= new TextPrinter(methods);
/* second routine >> */ //_handler -= methods;
}
private static void InvokePrinter(string message)
{
_handler(message);
}
private static void PushMessage(string message)
{
Console.WriteLine("# :: {0}", message);
}
Run Code Online (Sandbox Code Playgroud)
如果我使用第二个例程UnRegisterHandler,一切都按照它应该的方式工作.但是当我使用第一个PushMessage方法时,该方法将不会从调用列表中删除,_handler尽管有或没有,new我猜它必须正常工作.那么,这里的问题是什么?
谢谢.
你在这里有两种不同的语法:
DelegateType x = new DelegateType(MethodName)DelegateType x = new DelegateType(ExistingDelegateInstance)那些做不同的事情 - 第一个基于方法组转换构建新的委托实例.这完全等同于:
DelegateType x = MethodName;
Run Code Online (Sandbox Code Playgroud)
第二个构建一个新的委托实例,它有效地"重定向"到现有实例,并且不等于它.这很容易证明:
using System;
public class Test
{
static void Main()
{
Action action1 = Main;
Action action2 = new Action(Main);
Action action3 = new Action(action1);
Console.WriteLine(action1.Equals(action2)); // True
Console.WriteLine(action1.Equals(action3)); // False
}
}
Run Code Online (Sandbox Code Playgroud)
这是非常罕见的好主意,创建引用到另一个新的委托实例,除非它是委托方的缘故-这也是更好地处理比以前要通过引用转换(有一个引用转换从Action<string>到Action<object>例如,没有失去身份).