【问题标题】:Why can't I put a delegate in an interface?为什么我不能将委托放在接口中?
【发布时间】:2010-10-11 09:48:09
【问题描述】:

为什么我不能向我的界面添加代理?

【问题讨论】:

    标签: c# .net syntax delegates interface


    【解决方案1】:

    Delegatetype,不能在接口中声明。您可能希望使用事件(如果合适)或在接口外部但在同一命名空间中声明委托。

    此链接可能会有所帮助-When to Use Delegates Instead of Interfaces

    【讨论】:

      【解决方案2】:

      Delegate 只是另一种类型,因此将其放在界面中不会有任何好处。

      您不需要创建自己的委托。大多数情况下,您应该只使用 EventHandler、Func、Predicate 或 Action。

      请问你的代表长什么样子?

      【讨论】:

      • 这个答案实际上也解决了我的问题,即在我想使用委托的情况下,我永远找不到使用委托的好方法。 IE。不要使用'm :)。
      【解决方案3】:

      您可以使用以下任何一种:

      public delegate double CustomerDelegate(int test);
      public interface ITest
      {
          EventHandler<EventArgs> MyHandler{get;set;}
          CustomerDelegate HandlerWithCustomDelegate { get; set; }
          event EventHandler<EventArgs> MyEvent;
      }
      

      【讨论】:

      • 既然可以使用 Func 为什么还要创建 CustomerDelegate?
      • 我知道,我只是在说明你几乎可以使用任何东西 :)
      • Func 这样的参数很难理解。为该签名命名更有意义。
      • 跨 COM 工作时,您实际上必须使用自己的委托,因为您无法编组诸如 Func、EventHandler、Action 等泛型类型。
      【解决方案4】:

      文档清楚地表明您可以在接口中定义委托:

      一个接口只包含 方法、委托或 事件。

      MSDN: interface (C# Reference)

      但是,在同一页的注释中,它说接口可以包含方法、属性、索引器和事件的签名。

      如果您尝试将委托放在接口中,编译器会说“接口不能声明类型”。

      Ecma-334 标准(8.9 接口)同意该页面和编译器上的注释。

      【讨论】:

      • 这看起来像是 MSDN 中的错误。那应该是“方法、属性或事件的签名”,不是吗?
      【解决方案5】:

      这是一个委托 TYPE 声明...

      public delegate returntype MyDelegateType (params)
      

      this 不能在接口中声明,因为它是类型声明

      但是使用上面的类型声明,您可以使用委托实例

      MyDelegateType MyDelegateInstance ( get; set;)
      

      所以委托实例是可以的,但委托类型声明不是(在接口中)

      【讨论】:

      • 迄今为止的最佳答案。说到点子上了。我非常喜欢人们直奔主题而不是写演讲。
      【解决方案6】:

      正如其他人所提到的,您只能在接口外部定义委托。

      使用委托几乎没有错。 我个人认为Func&lt;int, double&gt; 不如使用委托:

      1. 您不能命名参数,因此参数含义可能不明确
      2. Events 不是线程安全的已经是老消息了,因此下面的代码并不理想:

        if (MyFuncEvent != null)
        {
            MyFuncEvent(42, 42.42);
        }
        

        见:http://kristofverbiest.blogspot.com/2006/08/better-way-to-raise-events.html

        更安全的代码是:

        MyFuncEventHandler handler = MyFuncEvent;
        if (handler != null)
        {
            handler(42, 42.42);
        }
        
      3. 如果你想将事件的签名保存到一个变量中,你必须复制它(或者你可以使用我不喜欢的var)。如果您有很多争论,那么这可能会变得非常乏味(同样,您可能总是很懒惰并使用var)。

        Func<int, double, string, object, short, string, object> handler = MyFuncEvent;
        if (handler != null)
        {
            handler(42, 42.42, ...);
        }
        

      委托使您不必在每次要将其分配给变量类型时复制方法/事件的签名。

      【讨论】:

      • 但是,请注意,您可以在 lambda 函数的调用点命名参数(但仅限于两个以上):Action f = (int i, int j) => { }; /* 等同于 */ var g = (Action)((i, j) => { });奇怪的是,在使用前一种语法时(这是最不需要的时候),你不能使用 'var'。
      【解决方案7】:

      接口方法可以接受委托作为参数,没有问题。 (也许我没有看到问题?)但是如果打算在接口中指定出站调用,请使用事件。

      有这么多的小细节,只显示一些代码而不是试图用散文来描述它要容易得多。 (抱歉,连代码示例都有些臃肿了……)

      namespace DelegatesAndEvents
      {
          public class MyEventArgs : EventArgs
          {
              public string Message { get; set; }
              public MyEventArgs(string message) { Message = message; }
          }
      
          delegate void TwoWayCallback(string message);
          delegate void TwoWayEventHandler(object sender, MyEventArgs eventArgs);
      
          interface ITwoWay
          {
              void CallThis(TwoWayCallback callback);
      
              void Trigger(string message);
              event TwoWayEventHandler TwoWayEvent;
          }
      
          class Talkative : ITwoWay
          {
              public void CallThis(TwoWayCallback callback)
              {
                  callback("Delegate invoked.");
              }
      
              public void Trigger(string message)
              {
                  TwoWayEvent.Invoke(this, new MyEventArgs(message));
              }
      
              public event TwoWayEventHandler TwoWayEvent;
          }
      
          class Program
          {
              public static void MyCallback(string message)
              {
                  Console.WriteLine(message);
              }
      
              public static void OnMyEvent(object sender, MyEventArgs eventArgs)
              {
                  Console.WriteLine(eventArgs.Message);
              }
      
              static void Main(string[] args)
              {
                  Talkative talkative = new Talkative();
      
                  talkative.CallThis(MyCallback);
      
                  talkative.TwoWayEvent += new TwoWayEventHandler(OnMyEvent);
                  talkative.Trigger("Event fired with this message.");
      
                  Console.ReadKey();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-03-05
        • 1970-01-01
        • 2021-07-25
        • 1970-01-01
        • 2011-07-26
        • 2011-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多