为什么我不能在一个接口中放一个委托?

时间:2009-03-04 23:22:15

标签: c# .net syntax delegates interface

为什么我不能在我的界面中添加委托?

7 个答案:

答案 0 :(得分:33)

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

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

答案 1 :(得分:24)

委托只是另一种类型,所以你不能通过把它放在界面中来获得任何东西。

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

我可以问你的代表是什么样的吗?

答案 2 :(得分:7)

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

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

答案 3 :(得分:6)

这是委托TYPE decalaration ...

public delegate returntype MyDelegateType (params)

这不能在接口中声明,因为它是一个类型声明

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

MyDelegateType MyDelegateInstance ( get; set;)

所以委托实例没问题,但代理类型声明不是(在界面中)

答案 4 :(得分:4)

文档明确指出您可以在界面中定义委托:

  

界面仅包含   方法,代表或的签名   事件

MSDN: interface (C# Reference)

但是,在同一页面上的备注中,它表示接口可以包含方法,属性,索引器和事件的签名。

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

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

答案 5 :(得分:1)

正如其他人所提到的,您只能在界面之外定义代理

使用代表几乎没有错。 我个人认为Func<int, double>不如使用代表那么可取:

  1. 您无法命名参数,因此参数含义可能不明确
  2. 事件不是线程安全的老消息,因此以下代码并不理想:

    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, ...);
    }
    
  4. 代表可以避免每次要将其分配给变量类型时复制方法/事件的签名。

答案 6 :(得分:0)

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

有很多细节,只是展示一些代码而不是试图在散文中描述它们要容易得多。 (对不起,即使代码示例有点臃肿......)

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();
        }
    }
}