2011-10-12 103 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

相关问题