代码之家  ›  专栏  ›  技术社区  ›  mattdlong

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

  •  1
  • mattdlong  · 技术社区  · 14 年前

    我只是在看我的一些代码,我突然想到,

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

    因为我可以直接将一个方法分配给委托,为什么我不能直接对该方法调用BeginInvoke呢?此代码的读取方式表明委托分配是多余的。

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

    4 回复  |  直到 11 年前
        1
  •  2
  •   Reed Copsey    14 年前

    方法不是委托-a delegate 是引用方法的不同类型-委托中的信息实际上多于方法。

    从技术上讲,编译器可能会为您连接并缩短输入时间,但实际上我有点庆幸没有完成。通过强制您将委托分配给对象上的方法引用,然后使用BeginInvoke调用委托,编译器将强制您在此处更加明确地表达自己的愿望。

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

    也就是说,在.NET4中,我建议您更改“后台线程”中“激发方法”的方式。我建议不要使用delegate.begininvoke,而是考虑改为使用新的任务类:

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

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

        2
  •  1
  •   Grzenio    14 年前

    这里有一些句法上的糖分。委托实际上是一个包装方法的对象,它恰好定义了BeginInvoke方法。语法上的制糖是,您可以将“方法”分配给委托(而不显式地创建委托),但它只在这个上下文中工作。

        3
  •  0
  •   STO    14 年前

    我想是故意的。在C中,方法不是功能语言中的对象,而是委托。

    委托构造函数是C编译器支持的“接触点”,在这里方法被用作“方法引用”而不是“方法调用”。

    使用SomeInstance.Method.SomeMethodOfMethod访问“实例的方法实例”对象时,语法混乱,需要方法实例。有些人可能期望从同一对象的同一方法获得的方法实例也必须相同,这将需要额外的内存使用来将方法实例存储在对象中。

        4
  •  0
  •   supercat    11 年前

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