看来C#4.0不支持覆盖中参数的协方差(使用“in”关键字);是这样吗?
如果是这样,有更优雅的方法吗?
CONTEXT
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社区。 p>
答案 0 :(得分:7)
首先,参数类型协方差是 not typesafe 。假设我们允许参数类型协方差:
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.
不,协方差根本不是你想要的。这是不安全的。您希望返回类型上的协方差,而不是参数类型上的协方差。在您想要的参数类型 contravariance :
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#既不支持返回类型协方差也不支持参数类型逆转。遗憾!
答案 1 :(得分: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);
}
}