无法从委托对象调用列表中正确删除方法
Can't remove methods from delegate object invocation list properly
正如我在这里和那里读到的那样,在 C# 中使用或不使用委托对象的 new
关键字在调用列表中添加或删除方法是完全相同的,并且会产生相同的 IL。例如看这个:What is the difference between two ways of using delegates in C# (with new keyword and without) 有这段代码:
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += this.button1_Click;
两者没有区别。但是当我使用 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);
}
如果我使用 UnRegisterHandler
中的第二个例程,一切都会按预期进行。但是当我使用第一个时,PushMessage
方法不会从 _handler
的调用列表中删除,尽管有或没有 new
我想它一定工作正常。那么,这里的问题是什么?
谢谢。
这里有两种不同的语法:
DelegateType x = new DelegateType(MethodName)
DelegateType x = new DelegateType(ExistingDelegateInstance)
它们做不同的事情 - 第一个基于 方法组转换 构建一个新的委托实例。这完全等同于:
DelegateType x = MethodName;
第二个构建一个新的委托实例,该实例实际上 "redirected" 现有实例,但不等于它。这很容易证明:
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
}
}
创建一个引用另一个委托实例的新委托实例很少是个好主意,除非它是为了委托差异 - 这也比以前通过引用转换更好地处理(有一个引用转换例如,从 Action<string>
到 Action<object>
,不会丢失身份)。
正如我在这里和那里读到的那样,在 C# 中使用或不使用委托对象的 new
关键字在调用列表中添加或删除方法是完全相同的,并且会产生相同的 IL。例如看这个:What is the difference between two ways of using delegates in C# (with new keyword and without) 有这段代码:
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += this.button1_Click;
两者没有区别。但是当我使用 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);
}
如果我使用 UnRegisterHandler
中的第二个例程,一切都会按预期进行。但是当我使用第一个时,PushMessage
方法不会从 _handler
的调用列表中删除,尽管有或没有 new
我想它一定工作正常。那么,这里的问题是什么?
谢谢。
这里有两种不同的语法:
DelegateType x = new DelegateType(MethodName)
DelegateType x = new DelegateType(ExistingDelegateInstance)
它们做不同的事情 - 第一个基于 方法组转换 构建一个新的委托实例。这完全等同于:
DelegateType x = MethodName;
第二个构建一个新的委托实例,该实例实际上 "redirected" 现有实例,但不等于它。这很容易证明:
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
}
}
创建一个引用另一个委托实例的新委托实例很少是个好主意,除非它是为了委托差异 - 这也比以前通过引用转换更好地处理(有一个引用转换例如,从 Action<string>
到 Action<object>
,不会丢失身份)。