为什么在订阅事件时要使用“new”关键字?(C#)

5
以下两种方式订阅事件有何区别?
receiver.ConfigChanged += Config_ConfigChanged;

receiver.ConfigChanged += new EventHandler(Config_ConfigChanged);

看起来它们两个的工作方式相同,但如果是这样的话,使用第二种方法有什么意义呢?

退订方面呢?这两种方法是否也可以同样有效?

receiver.ConfigChanged -= Config_ConfigChanged;

receiver.ConfigChanged -= new EventHandler(Config_ConfigChanged);

1
可能是[+= new EventHandler(Method) vs += Method]的重复问题 (https://dev59.com/i3E85IYBdhLWcg3wgDlI)。 - James
https://dev59.com/iHVD5IYBdhLWcg3wTJrF - Connell
它们是相同的。代码生成器更喜欢长格式,但你可以使用短格式。请注意-= new看起来多么令人困惑。 - H H
4个回答

13

长的方式在所有版本的C#中都可以使用,而短的方式只能在C# 2及更高版本中使用。因此,我认为现在没有理由使用冗长的方式。

有一些情况下仍需要使用new DelegateType(methodGroup),但是事件订阅不是其中之一。这些情况通常涉及泛型类型推断或方法重载。

取消订阅无论哪种方式都有效,因为它基于值相等性,而不是引用相等性。如果我没记错,从方法组进行的隐式转换和显式的new将被转换为相同的IL代码。隐式转换只是语法糖。


是的,我同意。不过很烦人的是,VS代码片段插入新事件处理程序仍然使用旧语法。 - Grokys
+1 - 谢谢你。我显然还停留在黑暗时代 :) - ChrisBD

2
Visual Studio的TAB事件自动完成总是默认使用.NET 1.0的做法,无论你使用哪个版本的框架。你可能会发现一些人习惯于阅读旧的做法。我只是通过使用Resharper才发现了更简洁的方式!这里有一个MSDN文章介绍了事件订阅 - 正如@CodeInChaos刚刚确认的那样:http://msdn.microsoft.com/en-us/library/ms366768%28v=vs.80%29.aspx

0

好的,所以

receiver.ConfigChanged -= Config_ConfigChanged;

将清除所有引用该方法的事件处理程序。

var eventHandler = new EventHandler(Config_ConfigChanged); 

receiver.ConfigChanged += eventHandler;
receiver.ConfigChanged += new EventHandler(Config_ConfigChanged); 

receiver -= eventHandler;

只会清除一个事件处理程序。

如果您不关心跟踪处理程序,可以使用冗长的方式。


你确定这两个例子之间有区别吗? - CodesInChaos
这是一段时间以前的事情了,所以我记不清了,但我通常会测试这些东西,以防有人告诉我我错了 :) - Dave Walker

0

如果我错了,请纠正我,但我不知道这是否有效

receiver.ConfigChanged += new EventHandler(Config_ConfigChanged);
receiver.ConfigChanged -= new EventHandler(Config_ConfigChanged);

因为这是两个不同的实例,所以我认为会这样。

var configChanged = new EventHandler(Config_ConfigChanged);
receiver.ConfigChanged += configChanged;
receiver.ConfigChanged -= configChanged;

不过,又何妨直接使用呢?

receiver.ConfigChanged += Config_ConfigChanged;
receiver.ConfigChanged -= Config_ConfigChanged;

你是,嗯,单词(错误?)。第一个示例由事件系统特殊处理,将按预期工作。 - Grokys
我从未查过这个,但我也一直认为是这样的。如果我需要删除一个事件,我总是在该类中声明EventHandler实例作为变量,然后我可以从事件中删除该实例。我实际上经常这样做,读完这个问题后,我开始问自己是否可以节省很多时间。 - Connell
2
“-” 运算符在委托上不使用引用相等性,因此所有这些都可以工作。我也希望 C# 编译器将第一个和第三个代码转换为相同的 IL。所以从技术上讲,事件系统并没有执行任何特殊情况,而是 Delegate.Remove 使用值相等性而不是引用相等性。这种行为自然地传播到了“事件”。 - CodesInChaos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接