【问题标题】:Callback delegate with value type behaviour具有值类型行为的回调委托
【发布时间】:2015-03-27 02:52:51
【问题描述】:

考虑以下演示

    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)不被对象调用。

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

【问题讨论】:

  • 您链接到的帖子已经讨论了Delegates 是不可变引用类型。就像System.String

标签: c# delegates


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多