2011-10-12 111 views
0

考慮這兩個抽象類。 MyClass2擴展了我的BaseClass並覆蓋了一個虛擬方法。請注意,它還將MyBaseClass的TValue定義爲IList ...覆蓋具有通用返回類型的虛擬方法

public abstract class MyBaseClass<TKey, TValue> 
{ 
    public virtual IList<TValue> DoSomeStuff() 
    { 
     IList<TValue> result; 
     .... 
     return restult; 
    } 
} 

public abstract class MyClass2<TKey, TValue>: MyBaseClass<TKey, IList<TValue>> 
{ 
    public override IList<TValue> DoSomeStuff() 
    { 
     IList<TValue> result; 
     .... 
     return restult; 
    } 
} 

此代碼不能編譯。投訴在MyClass2.DoSomeStuff的返回類型上。錯誤是「當覆蓋方法時不能更改返回類型」IList<TValue> MyClass2<TKey, TValue>.DoSomeStuff()

我不清楚爲什麼這是錯誤的。爲什麼編譯或.net認爲override方法的TValue是MyClass2的?

回答

3

在你的基類部分的問題的:

public abstract class MyClass2<TKey, TValue>: MyBaseClass<TKey, IList<TValue>> 

更換IList<TValue>TValue,它會工作 - 方法已經返回IList

3

TValue參數的基類,如繼承了你的子類,實際上是IList<TValue>由子類中聲明,內TValue屬於你的子類。

所以,如果你想覆蓋現有的屬於基類的虛方法,返回類型實際上預計爲IList<IList<TValue>>;即0屬於您的基類的TValue的,而不是子類。

+0

hrmm。然後我想保持類型相同的唯一方法是「泛化」方法本身。泛型和繼承似乎比較麻煩一些。 – mike01010

+0

@ mike01010從你顯示的有限代碼中,如果你想讓'DoSomeStuff'仍然返回'IList ' –

1

你得到的錯誤,因爲TValue在子類實際上是在基類IList<TValue>因此該方法的簽名(如您的基類,會看到它)會IList<IList<TValue>>這顯然不符合虛擬方法的簽名。

要獲得匹配的類型,你就必須更改簽名:

public override TValue DoSomeStuff() 
{ 
    TValue result; 

    return result; 
} 
+0

我會改變類爲'MyClass2 :MyBaseClass 改爲虛擬方法的簽名。 – BoltClock

+0

@BoltClock - 這一切都取決於哪一個實際上是錯誤的。我假設基類會有其他可能有完全不同實現的孩子。在那種情況下,你將不得不修改孩子。 –

+0

TKey和TValue用於詞典。在某些類中,Dictionary將單個值存儲在其他List(multimap)中。例如它可能會存儲{int,MyObject}或{int,IList }。我猜我可能會試圖讓這些類在這種情況下做太多。 – mike01010