为什么我不能直接在方法上调用BeginInvoke而不必将其分配给委托?

时间:2010-06-21 19:20:07

标签: c# delegates

我只是在查看我的一些代码,并且在我看来,给出了

      Action<int> fireMessage = FireMessages;
      fireMessage.BeginInvoke(1, r => fireMessage.EndInvoke(r), null);

由于我可以直接将方法分配给委托,为什么我不能直接在方法上调用BeginInvoke。此代码读取的方式表明委托分配是多余的。

但直接在方法上调用BeginInvoke会引发编译器异常。

4 个答案:

答案 0 :(得分:2)

方法不是委托 - delegate是引用方法的不同类型 - 委托中实际上有更多信息而不仅仅是方法。

从技术上讲,编译器可能会为你填写这个并缩短输入时间,但我实际上有点感谢你没有这样做。通过强制您将一个委托分配给一个对象的方法引用,然后使用BeginInvoke调用该委托,编译器会强迫您在此处更加明确。

通过BeginInvoke调用委托可能会产生一些严重的副作用 - 这应该是一个明确的,有目的的操作。如果在单独的线程中调用它们,许多方法将不会按预期运行,至少这样,您需要知道您正在做什么才能以这种方式工作。

话虽如此,在.NET 4中,我建议改变你在“后台线程”中“触发方法”的方式。而不是使用Delegate.BeginInvoke,我建议考虑更改为使用新的Task类:

Task.Factory.StartNew( () => FireMessages(1) );

新任务库有许多优点,特别是在错误处理,取消,防止线程池上的超额预订等方面。

答案 1 :(得分:1)

这里有一些语法糖。委托实际上是一个包装方法的对象,它恰好定义了BeginInvoke方法。语法糖是您可以为委托分配“方法”(不显式创建委托),但它只适用于此上下文。

答案 2 :(得分:0)

我认为这是设计上的。在C#中,方法不是像函数式语言那样的对象,而是委托。

委托构造函数是C#编译器支持的“触摸点”,这是单个地方,其中方法用作“方法引用”而不是“方法调用”。

使用someInstance.Method.SomeMethodOfMethod访问'instance的方法实例'对象会产生令人困惑的语法,并且需要方法实例。有些人可能期望从同一对象的相同方法获得的方法实例也必须相同,这将需要额外的内存使用来在对象内存储方法实例。

答案 3 :(得分:0)

如果编译器知道要生成的委托类型,它可以自动从方法组生成委托。但是,它不能推断基于方法组的委托类型,因为不同的委托类型通常不兼容,即使签名匹配也是如此。尽管在许多情况下编译器实际上可以使用具有特定签名的任何委托,但编译器无法知道这些情况是什么。因此,在编译器可以通过其他方式识别委托类型的情况下,方法组仅被隐式转换为委托。