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

C# Explicitly override virtual interface method of base type

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

为了简单起见,我继续将一些我经常使用的东西放在数据库中 class,因此不需要转换:

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];

这些方法随后在基础 classes 中被覆盖。或者不是,在这种情况下它会在使用时抛出异常。为了使事情更简单一些,我还想以类似的方式实现 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>>,我 运行 遇到了无法覆盖数据库 GetEnumerator() 的问题。我尝试了多种不同的方式:

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

The modifier 'override' is not valid for this item (CS0106)

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


相关问答"C# overriding an interface contract method of a base class"没有解决问题。如果您要将 x 的类型更改为 TestBase,代码输出 "Base".

现在,我以前 运行 遇到过这类问题,这通常是 做某事太傻太复杂的情况.我能想到的一个明显的解决方案是将实现直接移动到 DataBase class 中:

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

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

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

It is a compile-time error for an explicit interface member implementation to include access modifiers, and it is a compile-time error to include the modifiers abstract, virtual, override, or static.

所以如果你想覆盖 DataDictionary 中的 DataBase::GetEnumerator(),你需要一个非显式的实现。但是为了使用非显式实现编写覆盖,您必须显式实现 IEnumerable<KeyValuePair<string, DataBase>>::GetEnumerator(),因为如果您对 that 方法使用非显式实现,它将隐藏 DataBase::GetEnumerator(),因为这两种方法仅在 return 类型上有所不同。

底线:我不明白你为什么要设计这样的东西。 (当您将其描述为“doing-something-way-too-silly-and-complicated!”)

时,您似乎在回答中得出了相同的结论