对于模拟事件,是应该维护一个委托列表还是使用多播委托?

时间:2012-11-25 07:48:13

标签: c# delegates

这两个班级有什么区别?哪个更好?

class MulticastExample
{
    delegate void ME();

    ME me;

    public MulticastExample()
    {
        ME a = new ME(() => Console.WriteLine("A"));
        ME b = new ME(() => Console.WriteLine("B"));

        me = a + b;
    }

    public void Run()
    {
        me();
    }
}

-

class ListExample
{
    delegate void LE();

    List<LE> le = new List<LE>();

    public ListExample()
    {
        LE a = new LE(() => Console.WriteLine("A"));
        LE b = new LE(() => Console.WriteLine("B"));

        le.Add(a);
        le.Add(b);
    }

    public void Run()
    {
        foreach (var x in le)
        {
            x();
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我认为你应该使用第一个例子。请注意,您始终可以通过me.GetInvocationList()获取“多播”代理中的项目列表。类型MulticastExample.MESystem.Delegate继承此方法。

当您分配到ab时,您不必使用new语法。相同的委托由以下人员创建:

ME a = () => Console.WriteLine("A");

请注意,ME的每个实例都是不可变的,并且具有固定长度的调用列表。此列表保证至少包含一个项目。

当您“添加”或“减去”(合并或删除)委托时,原始实例将保持不变(不变性)并创建新实例。

如果“减法”的结果如:

ME c = b - a;

将提供零长度多播委托,不会创建新实例,而是返回null引用(即c变为null)。因此,请在调用之前记住null检查:c();

如果您选择使用List<T>,则有一个区别(正如您现在可能知道的那样)List<>是可变的。另请注意,您有责任检查List<>中没有成员本身是多播的,因为.NET中的任何委托类型都允许多个项目的调用列表。

最后(但我想你知道),像ME这样的委托类型不必嵌套在其他类型(在这种情况下是class MulticastExample)中,但是当你希望委托类型成为包含类的“实现细节”时,这很好。

如果您计划将委托类型设置为泛型类型,如果您打算与+结合使用,请不要在其任何类型参数中使此类型为逆变(或此处不太有用的协变)。< / p>

答案 1 :(得分:1)

使用MulticastExample,对me的一次调用会将所有方法subscribed调用到它。所以ab将通过单个方式调用致电me

使用ListExample,您必须单独调用每个代理人。因此,您必须单独调用 所做的ab foreach循环


如果ab将引用相同签名的单个方法,则ListExample是多余的。您应该使用MulticastExample