As I read here and there a little, adding to or removing methods from the invocation list with or without the new
keyword of a delegate object in C# is exactly the same and produces the same IL. See this one for example: What is the difference between two ways of using delegates in C# (with new keyword and without) that had this fragment of code:
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button1.Click += this.button1_Click;
No difference between those two. But I accidentally came across observing the unusual output with this code when I used delegate
for passing as method parameter:
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);
}
If I use the second routine in UnRegisterHandler
, everything works as how it should. But when I use the first one, the PushMessage
method won't be removed from the invocation list of _handler
although that with or without new
I guess it must have worked properly. So, what is the issue here?
Thanks.
You've got two different syntaxes here:
DelegateType x = new DelegateType(MethodName)
DelegateType x = new DelegateType(ExistingDelegateInstance)
Those do different things - the first builds a new delegate instance based on a method group conversion. That's entirely equivalent to just:
DelegateType x = MethodName;
The second builds a new delegate instance which is effectively "redirected" to the existing instance, and isn't equal to it. This is easily demonstrated:
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
}
}
It's very rarely a good idea to create a new delegate instance which refers to another one, unless it's for the sake of delegate variance - which is also better handled than it used to be via reference conversions (there's a reference conversion from Action<string>
to Action<object>
for example, with no loss of identity).
See more on this question at Stackoverflow