为什么某些结构继承接口,但不实现其所有成员?

时间:2019-05-17 14:49:45

标签: c# inheritance struct interface .net-core

在.NET Core中进行编程时,我偶然发现了一个名为StringValues的结构。它来自Microsoft.Extensions.Primitive程序集,并保存在同一命名空间下。其源代码可在GitHub上找到。

我注意到它继承了一些接口:

  • IList<string>
  • ICollection<string>
  • IEnumerable<string>
  • IEnumerable
  • IReadOnlyList<string>
  • IReadOnlyCollection<string>
  • IEquatable<StringValues>
  • IEquatable<string>
  • IEquatable<string[]>

我想说,对于一个结构来说,这很多。当我查看其方法(在Visual Studio定义查看器中)时,我注意到它确实提供的很少。例如,我没有看到ICollection<T>Add()Clear()的基本Remove()方法。

当我尝试将StringValues的实例强制转换为ICollection<string>并使用Add()时:

var stringValues = new StringValues("Foo");
var stringCollection = stringValues as ICollection<string>;
stringCollection.Add("Bar");

我最终在NotSupportedException方法调用中抛出了Add()

  

NotSupportedException:不支持指定的方法。

所以我去了源代码(开源的无穷优势),看看发生了什么!然后我看到了:

void ICollection<string>.Add(string item)
{
    throw new NotSupportedException();
}

void IList<string>.Insert(int index, string item)
{
    throw new NotSupportedException();
}

bool ICollection<string>.Remove(string item)
{
    throw new NotSupportedException();
}

void IList<string>.RemoveAt(int index)
{
    throw new NotSupportedException();
}

void ICollection<string>.Clear()
{
    throw new NotSupportedException();
}

问题

这种编程方式有什么意义?尽管如此,我总是通过从接口继承来声明,可以将特定类型与继承的接口同等使用。

在这种情况下,似乎该结构不是要在公共场合使用?在查看已实现的Contains()方法时会感到这种感觉,但仍然被标记为内部:

bool ICollection<string>.Contains(string item)
{
    return IndexOf(item) >= 0;
}

1 个答案:

答案 0 :(得分:3)

因为这样做通常有用,只要调用者仅调用可用方法即可。他们可以检查类似IList.IsReadOnly之类的事物来预期这一点-如果返回false,他们应该知道不要期望Add等起作用。

将结构上不可变的类型传递给采用过去一直采用可变API的API的对象,例如IList,因为同一个接口还提供了其他有用的功能

类似地,Stream具有CanReadCanWrite之类的东西,并且如果其中一个返回false,则可以预期相应的读/写API会失败。