1

如果我有一个通过(例如)FrobbingEventArgs 引发事件的类,我是否可以使用采用 EventArgs 的方法来处理它?

这是一些代码:

class Program
{
   static void Main(string[] args)
   {
      Frobber frobber = new Frobber();
      frobber.Frobbing += FrobberOnFrobbing;
      frobber.Frob();
   }

   private static void FrobberOnFrobbing(object sender,
       EventArgs e)
   {
      // Do something interesting. Note that the parameter is 'EventArgs'.
   }
}

internal class Frobber
{
   public event EventHandler<FrobbingEventArgs> Frobbing;
   public event EventHandler<FrobbedEventArgs> Frobbed;

   public void Frob()
   {
      OnFrobbing();

      // Frob.

      OnFrobbed();
   }

   private void OnFrobbing()
   {
      var handler = Frobbing;
      if (handler != null)
         handler(this, new FrobbingEventArgs());
   }

   private void OnFrobbed()
   {
      var handler = Frobbed;
      if (handler != null)
         handler(this, new FrobbedEventArgs());
   }
}

internal class FrobbedEventArgs : EventArgs { }
internal class FrobbingEventArgs : EventArgs { }

我问的原因是 ReSharper 似乎对 XAML 中的等效项有问题(看起来像),我想知道这是 ReSharper 中的错误,还是我对 C# 的理解有误。

4

3 回答 3

6

也许协变不是这个词

关闭。你要找的词是逆变的。方法组到委托类型的转换在返回类型中是协变的,在形式参数类型中是逆变的。

这是我关于这个主题的博客文章:

https://docs.microsoft.com/en-us/archive/blogs/ericlippert/covariance-and-contravariance-in-c-part-three-method-group-conversion-variance

如果我有一个通过(例如)FrobbingEventArgs 引发事件的类,我是否可以使用采用 EventArgs 的方法来处理它?

好吧,你试过了,它奏效了,很明显是的。有关规范中的理由,请参阅标题为“方法组转换”的部分。

于 2010-05-14T14:53:18.683 回答
1

是的,您可以,但是当您访问事件处理程序中的 e 参数时,您将只能访问属于 EventArgs 基类的成员,除非您将其转换为派生类型。我认为这个词是多态的而不是协变的,C# 中的所有类都是多态的,这是一种语言特性。

于 2010-05-14T10:49:12.663 回答
-1

由于事件只能从声明它们的类中调用,因此您的派生类不能直接调用在基类中声明的事件。

您可以通过为事件创建受保护的调用方法来实现您想要的。通过调用此调用方法,您的派生类可以调用该事件。

为了获得更大的灵活性,调用方法通常被声明为虚拟的,这允许派生类覆盖它。这允许派生类拦截基类正在调用的事件,可能对它们进行自己的处理。

你可以做:

protected void OnFrobbing(EventArgs e) 
   { 
      var handler = Frobbing; 
      if (handler != null) 
         handler(this, new e); 
   } 

或者:

protected virtual void OnFrobbing(EventArgs e) 
   { 
      var handler = Frobbing; 
      if (handler != null) 
         handler(this, new e); 
   } 
于 2010-05-14T11:05:24.113 回答