1

似乎 C# 4.0 不支持覆盖参数的协方差(使用“in”关键字);是这样吗?

如果是这样,有没有更优雅的方法来做到这一点?

语境

public interface IBaseEvent { /* ... */ }

public interface IDerivedEvent : IBaseEvent { /* ... */ }

public class MoreDerivedEvent : IDerivedEvent { /* ... */ }

我有一组处理MoreDerivedEvent. 由于事件处理代码的限制,我只能为 注册一个事件处理程序MoreDerivedEvent,而且我不知道它会将注册接口作为事件处理(我不相信它会,因为指导是显式使用类)。因此,为了适当地处理事件,我将处理程序定义如下:

public class BaseType
{
    protected virtual void Handle(IBaseEvent @event) { /* Do Base Stuff */ }
}

public class DerivedType
{
    protected virtual void Handle(IDerivedEvent @event)
    {
        /* Do Derived Stuff */
        Handle((IBaseEvent)@event);
    }

    protected override sealed void Handle(IBaseEvent @event)
    {
        base.Handle(@event);
    }
}

这显然不能提供真正的继承,如果我不能解决这个问题,我可能只会展平派生自的DerivedType类型BaseType。但我想我会先把它放到 Stack Overflow 社区。

4

2 回答 2

7

首先,参数类型协方差不是类型安全的。假设我们允许参数类型协方差:

class B 
{
    public virtual void Frob(Animal a)
    {
    }
}
class D : B
{
    public override void Frob(Giraffe g)
    {
    }
}
....
B b = new D();
b.Frob(new Tiger());  // Calls D.Frob, which takes a giraffe.

不,协方差根本不是你想要的。这是不安全的。您需要返回类型的协变,而不是参数类型。在你想要逆变的参数类型上:

class B 
{
    public virtual void Frob(Giraffe g)
    {
    }
}
class D : B
{
    public override void Frob(Animal a)
    {
    }
}
....
B b = new D();
b.Frob(new Giraffe());  // Calls D.Frob, which takes any animal.

那里没问题。

不幸的是,C# 既不支持返回类型协变也不支持参数类型逆变。对不起!

于 2010-11-10T00:46:02.047 回答
2

首先,您需要一个接口来指定逆变换

public interface IBaseHandler<in T> where T : IBaseEvent
{
    void Handle(T handle);
}

然后你可以定义一个基类来做“基本的东西”

public class BaseType<T> : IBaseHandler<T> where T : IBaseEvent
{
    public virtual void Handle(T handle) { /* do base stuff */} 
}

这将允许您覆盖 MoreDerivedEvent

public class MoreDerivedType : BaseType<MoreDerivedEvent>
{
    public override void Handle(MoreDerivedEvent handle)
    {
        base.Handle(handle);
    }
}
于 2010-11-10T00:39:34.953 回答