C#显式覆盖基类型的虚拟接口方法

时间:2015-06-16 16:21:36

标签: c# inheritance override

我有一个抽象类DataBase,它用作不同类型数据的基类,例如简单值类型(byteintstring等。 )和更复杂的数据结构,如DataListDataDictionary。 DataList实现IList<DataBase>,DataDictionary实现IDictionary<string, DataBase>

为了简单起见,我继续并在DataBase类中添加了一些我经常使用的东西,因此无需进行强制转换:

public virtual DataBase this[string name] {
    get { throw new NotSuppportedException(); }
    set { throw new NotSuppportedException(); }
}
public virtual DataBase this[int index] { ...

// Example usage:
var someData = rootData["SomeList"][10];

然后在基类中重写这些方法。或者不是,在这种情况下,它会在使用时抛出异常。为了使事情变得更简单,我还希望以类似的方式实现IEnumerable<DataBase>

public virtual IEnumerator<DataBase> GetEnumerator() {
    throw new NotSuppportedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
    return GetEnumerator();
}

但由于DataDictionary是一个IDictionary,因此IEnumerable<KeyValuePair<string, DataBase>>,我遇到了无法覆盖DataBase GetEnumerator()的问题。我尝试了很多不同的方法:

(public|protected) (override) IEnumerator<DataBase> DataBase.GetEnumerator()
(public|protected) (override) IEnumerator<DataBase> IEnumerable<DataBase>.GetEnumerator()
  

修饰符&#39;覆盖&#39;对此项目无效(CS0106)

现在,我不确定在这个问题上该寻找什么 - 这甚至叫做什么? - 或者哪种限制(如果有的话)阻止我做我想做的事以及为什么会这样做。

相关问答"C# overriding an interface contract method of a base class"并未解决问题。如果您要将x的类型更改为TestBase,则代码会输出&#34; Base&#34;。

2 个答案:

答案 0 :(得分:1)

C#规范明确禁止在13.4.1部分中明确实现的接口成员上使用override

  

显式接口成员实现包含访问修饰符是编译时错误,包含修饰符abstractvirtualoverride是编译时错误,或static

因此,如果要覆盖DataBase::GetEnumerator()中的DataDictionary,则需要非显式实现。但是为了使用非显式实现编写覆盖,您必须已明确实现IEnumerable<KeyValuePair<string, DataBase>>::GetEnumerator(),因为如果对 方法使用非显式实现,它将隐藏{{ 1}},因为这两种方法的区别仅在于它们的返回类型。

结论:我不明白你为什么要设计这样的东西。 (当你把它描述为&#34; 做某事太过愚蠢和复杂的事情时,你的回答似乎得出了同样的结论!&#34;)

答案 1 :(得分:0)

现在,我之前遇到过这类问题,这通常是做某事 - 过于愚蠢和复杂的情况。我能想到的一个明显的解决方案是直接将实现转移到DataBase类:

public IEnumerator<DataBase> GetEnumerator() {
    if (this is DataList)
        return ((DataList)this).GetEnumerator();
    else if (this is DataDictionary)
        return ((DataDictionary)this).Values.GetEnumerator();
    else throw new NotSupportedException();
}

但显然,它绝对不是最干净的解决方案。