Почему некоторые структуры наследуют интерфейсы, но не реализуют все их члены? - PullRequest
1 голос
/ 17 мая 2019

При программировании на .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().

Когда я попытался в explicity привести экземпляр от StringValues к ICollection<string> и использовать Add():

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

, я получил NotSupportedException, брошенный в Add()вызов метода:

NotSupportedException: указанный метод не поддерживается.

Поэтому я отправился в исходный код (неоценимые преимущества open-source), чтобы посмотреть, чтопродолжается!И тогда я увидел:

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 Ответ

3 голосов
/ 17 мая 2019

Поскольку часто полезно делать , при условии, что вызывающая сторона только вызывает доступные методы. Они могут проверять такие вещи, как IList.IsReadOnly, чтобы предвидеть это - если это возвращает false, они должны знать, что Add и т. Д. Не сработают.

Может быть полезно передать структурно неизменный тип чему-то, что использует API, который исторически использует изменяемый API, например IList, потому что тот же интерфейс также предоставляет другие полезные функции .

Аналогично, Stream имеет такие вещи, как CanRead и CanWrite, и если любой из них вернет false, вы можете ожидать, что соответствующие API чтения / записи завершатся с ошибкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...