具有值类型行为的回调委托

时间:2015-03-26 18:46:47

标签: c# delegates

考虑以下演示

    class Program
{
    static void Main(string[] args)
    {
        MyCallBackClass myCallbackInstance = new MyCallBackClass();

        MyDelegate myDelegate = delegate() { /*Do nothing*/ };

        myDelegate += () => { Console.WriteLine("First"); };
        myDelegate += () => { Console.WriteLine("Second"); };

        myCallbackInstance.Callback = myDelegate;

        myDelegate += () => { Console.WriteLine("Third"); };

        myCallbackInstance.InvokeCallback();

        Console.ReadLine();
    }
}

delegate void MyDelegate();

class MyCallBackClass
{
    public MyDelegate Callback { get; set; }

    public void InvokeCallback()
    {
        if (Callback != null)
            Callback();
    }
}

由于委托是C#中的引用类型,如此处Why are delegates reference types?所示,我希望对象中的委托(" Callback")的引用指向与对象(" myDelegate")之外的引用相同的委托。令我惊讶的是,这个演示应用程序的输出是:

First
Second

,对象不会调用添加到委托(MulticastDelegate)的第三个元素。

这不是我期望的引用类型的行为,在我看来,委托被处理就好像它是一个值类型。我的假设在哪里错了?为什么不调用第三个委托元素?

2 个答案:

答案 0 :(得分:1)

语法someDelegate += someOtherDelegate;不会修改任何委托。相反,它构造一个新的委托,其中包含原始文件中存在的所有方法,并将新委托存储到someDelegate;有问题的代表将在调用之后包含与之前相同的方法。

在您的示例中,myCallBackInstance.Callback在其中存储了对包含两个方法的委托的引用。变量myDelegate将在其中存储对包含三个方法的委托的引用。后一个赋值对先前创建的双方法委托没有影响。

答案 1 :(得分:0)

代理虽然引用类型是不可变的。 +=运算符不会改变委托的值(因为这样做是不可能的),而是创建一个新委托,表示旧委托与新委托相结合,然后将新委托分配给变量+ =运算符用于。