IReadOnlyList<T>
has no IndexOf()
for no good reason whatsoever.
Если вы действительно хотите найти повод для упоминания, то причина историческая:
Еще в середине девяностых, когда был основан C #, люди еще не совсем осознавали преимущества неизменяемости и доступности для чтения, поэтому интерфейс IList<T>
, который они встроили в язык, к сожалению, был изменчивым.
Правильнее было бы придумать IReadOnlyList<T>
в качестве базового интерфейса и заставить IList<T>
его расширять, добавляя только методы мутации, но этого не произошло.
IReadOnlyList<T>
был изобретен значительно позже IList<T>
, и к тому времени было уже слишком поздно переопределять IList<T>
и расширять его IReadOnlyList<T>
. Итак, IReadOnlyList<T>
был построен с нуля.
Они не могли заставить IReadOnlyList<T>
расширить IList<T>
, потому что тогда он унаследовал бы методы мутации, поэтому вместо этого они основали его на IReadOnlyCollection<T>
и IEnumerable<T>
. Они добавили индексатор this[i]
, но затем либо забыли добавить другие методы, такие как IndexOf()
, либо намеренно опустили их, поскольку они могут быть реализованы как методы расширения, что упростило интерфейс. Но они не предоставили никаких таких методов расширения.
Итак, вот метод расширения, который добавляет IndexOf()
к IReadOnlyList<T>
:
using Collections = System.Collections.Generic;
public static int IndexOf<T>( this Collections.IReadOnlyList<T> self, T elementToFind )
{
int i = 0;
foreach( T element in self )
{
if( Equals( element, elementToFind ) )
return i;
i++;
}
return -1;
}
Имейте в виду, что этот метод расширения не такой мощный, как метод, встроенный в интерфейс. Например, если вы реализуете коллекцию, которая ожидает IEqualityComparer<T>
в качестве конструктивного (или другого отдельного) параметра, этот метод расширения не будет знать об этом, и это, конечно же, приведет к ошибкам. (Спасибо Grx70 за указание на это в комментариях.)
person
Mike Nakis
schedule
20.02.2020