2010-11-10 121 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

相關問題