【问题标题】:Why this delegate assignment does not work and how to solve it?为什么这个委托分配不起作用以及如何解决它?
【发布时间】:2015-07-23 09:13:13
【问题描述】:

我有以下示例代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.del = this.EventHandler; <-- This does not build
    }

    public void EventHandler(object sender, PropertyChangedEventArgs e)
    {

    }

    public delegate void A(object sender, EventArgs e);

    private A del;
}

它抱怨委托分配。我怀疑这是由于协方差/逆变问题,老实说这是一个我不完全理解的概念。

有什么方法可以构建此代码吗?对于具有任何事件参数(从 EventArgs 继承)的任何事件,我都需要一个通用处理程序。

【问题讨论】:

  • 更改其中一个:EventHandler 方法中的PropertyChangedEventArgs 或委托中的EventArgs
  • 我需要一个通用处理程序来处理具有任何事件参数的任何事件(从 EventArgs 继承)。
  • 然后把PropertyChangedEventArgs改成EventArgs

标签: c# .net delegates covariance contravariance


【解决方案1】:

想象一下,这一行是编译好的:

        this.del = this.EventHandler;

那么,问题来了:

        // since del must accept ANY EventArgs descendant, this should be possible:
        del.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
        // since del's signature IS (object, PropertyChangedEventArgs), we must convert 
        // NotifyCollectionChangedEventArgs to PropertyChangedEventArgs
        // OOOPS...

我需要一个通用处理程序来处理带有任何事件参数的任何事件

使用带有此签名的处理程序:

public void EventHandler(object sender, EventArgs e)
{

}


// compiles just fine
this.Loaded += EventHandler;
this.Closing += EventHandler;
this.Drop += EventHandler;

【讨论】:

  • 这是指向我的答案,问题很简单。谢谢。
  • 问题是我有一个通用服务,它接收任何事件的处理程序作为 EventHandler 参数,并将其附加到通过反射检索的事件。它适用于 EventArgs,但不适用于任何接收从 EventArgs 继承的内容的处理程序。
【解决方案2】:

你可以找到关于委托方差和协方差的解释here

当您将方法分配给委托时,协变和逆变 提供将委托类型与方法匹配的灵活性 签名。协方差允许方法具有返回类型 比委托中定义的派生更多。逆变许可 一种方法,其参数类型的派生程度低于 委托类型。

【讨论】:

    【解决方案3】:

    方法签名必须与delegate 匹配。如果允许您尝试执行的操作,那么您可以将任何类型传递给从 EventArgs 继承的第二个参数,但它实际上需要 PropertyChangedEventArgs

    【讨论】:

      【解决方案4】:

      这样不行。在您的示例代码中,您的 EventHandler 方法要求 e 的类型为 PropertyChangedEventArgs,即比委托声明的类型更具体。

      反之亦然,即您的处理程序可能不如委托具体。

      【讨论】:

        【解决方案5】:

        应该是

        在方法重载中使用PropertyChangedEventArgs

        因为在将事件分配给任何代表时。他们的签名必须相同

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
        
                this.del = this.EventHandler; <-- This does not build
            }
        
            public void EventHandler(object sender, PropertyChangedEventArgs e)
            {
        
            }
        
            public delegate void A(object sender, PropertyChangedEventArgs e);
        
            private A del;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-10-03
          • 2023-01-24
          • 2012-12-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多