有时候最简单的问题会让我越来越喜欢C / C ++和C#。
今天坐在公共汽车上沉思着我记得的代表们 阅读somwhere,你不需要在实例化时使用new关键字 新代表。
例如:
public static void SomeMethod(string message)
{
...
}
...
public delegate void TestDelgate(string message); //Define a delegate
...........
//create a new instance ..METHOD 1
TestDelgate t = new TestDelgate(SomeMethod);
//OR another way to create a new instance ..METHOD 2
TestDelgate t = SomeMethod; //create a new instance ..METHOD 2
所以今天的问题是
方法2中引发了什么。编译器是否将方法2扩展为方法1,因此编写TestDelgate t = SomeMethod;只是一个捷径 TestDelgate t = new TestDelgate(SomeMethod);或者是方法2存在的另一个原因
你们认为方法1或方法2的可读性更好吗(这是一个主观问题,但我只是想对stackoverflow的一般意见有一种不科学的感觉: - )
答案 0 :(得分:4)
是的,方法2只是方法1的简写 - 至少在使用方法组的情况下。你也可以 使用:
TestDelegate t = new TestDelegate(someExistingDelegate);
允许方差(不仅仅是C#4的通用方差)并创建一个单独的委托......但这很少有用。
我个人选择2 ...方法组转换非常方便。特别是它使事件布线更简单:
button.Click += LoadDocument;
而不是
button.Click += new EventHander(LoadDocument);
后者只是有额外的毛茸茸 - 前者具有更好的信息密度。当您将委托作为方法参数传递时,这也很重要。例如,比较:
observable.Subscribe(new Action<string>(Console.WriteLine));
与
observable.Subscribe(Console.WriteLine);
除非您真正想要将方法组转换为哪种委托类型,否则我只使用隐式转换。
答案 1 :(得分:2)
引擎盖下,你的两种方法完全一样。只是编译器对你想要做的事情很聪明。这个小功能称为delegate inference,并在C#2.0中添加。
我认为你应该使用#2,并利用委托推理。它们编译为相同的IL,选项#2更短更简洁。阅读和理解代码的含义更容易,因为噪音更少。
答案 2 :(得分:1)
是的,它们被编译成同样的东西。
我更喜欢#2。只是因为它更短而且不那么笨拙。由于之前已定义,您已经知道它是TestDelegate。那么为什么要再写一次呢?
答案 3 :(得分:1)
它只是显式委托创建的合成糖。这是C#2.0中的introduced。您可能已经注意到,如果要求Visual Studio 2008创建事件处理程序,它仍然会生成旧式(方法1)语法;我总是用新语法手动替换它。
我通常更喜欢方法2中的较短形式。我只使用方法1一次:使用从本机代码调用的委托,因此无法进行垃圾收集。我想非常明确地创建和分配它。
答案 4 :(得分:1)
是糖。当你不得不写这个时,真正派上用场的那种糖:
someObj.Test -= new TestDelegate(SomeMethod);
什么?您必须使用 new 关键字删除事件处理程序。是的你是。 VB.NET团队对此非常痛苦,他们决定采用完全不同的语法:
RemoveHandler someObj.Test, AddressOf SomeMethod
即使上面的C#语句都是糖,真正的代码如下所示:
someObj.Test.remove(new TestDelegate(this, SomeMethod));
其中“remove”是事件的访问者函数。并且“this”是初始化Delegate.Target属性所必需的。现在很明显,它实际上是一个方法调用,并且使用new关键字突然再次有意义。隐藏“this”也有一些缺点,事件订阅不会再阻止对象被垃圾收集。
答案 5 :(得分:0)
引擎盖下两个语句创建委托对象并将参数传递给ctor:方法的地址和对此的引用。第二是语法糖。
答案 6 :(得分:0)
'new'语法的一个优点是它通知程序员正在分配一个新对象;如果希望避免重复创建新的相同代表,可以将代表拉出到一个字段。我知道事实上,一个人可以使用一个代表订阅而另一个代表可以取消订阅,但对我来说感觉不对。存储到代理用于订阅的字段,然后使用相同的委托取消订阅感觉更干净。恕我直言,如果订阅行为会返回一个MethodInvoker,当被调用时,将取消订阅(在这种情况下,“事件”只是一个接受EventHandler并返回MethodInvoker的函数),但是那是不是.net事件如何运作。