2010-11-10 100 views
1

似乎C#4.0不支持覆盖参数中的协方差(使用“in”关键字);是这样吗?.NET 4.0中有更好的方法来做到这一点吗?

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

背景

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); 
    } 
} 

这显然并不提供真正的继承,我可能就拼合从DerivedTypeBaseType如果我得到的类型无法解决这个问题。但我想我会先把它放到Stack Overflow社区。

回答

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#不支持返回类型协方差和参数类型的逆变。抱歉!

+0

感谢修改co-versus contravariance;我已经更新了问题和标签。 – arootbeer 2010-11-10 03:37:50

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 */} 
} 

那么这将让你重写for MoreDerivedEvent

public class MoreDerivedType : BaseType<MoreDerivedEvent> 
{ 
    public override void Handle(MoreDerivedEvent handle) 
    { 
     base.Handle(handle); 
    } 
} 
+0

+1 - 这是一个有趣的方法。在这种情况下,我不喜欢它,因为它引入了一个不会被使用的接口,根据定义,我的受保护的方法将会公开。 – arootbeer 2010-11-10 03:46:44

相关问题