Как выбрать между IList или IEnumerable в качестве типа параметра метода - PullRequest
0 голосов
/ 11 апреля 2019

Я пишу библиотеку и пытаюсь определить наилучший тип, который будет использоваться для параметров метода в методе.Я также пытаюсь определить, где провести черту между слишком требовательным и получением определения метода записи.

Вот некоторый код

public void MethodTakesIList(IList<MyClass> myClassInstances) {
  List<List<byte>> byteLists = GetByteLists(myClassInstances.Count);
  for (int i = 0; i < myClassInstances.Count; i++) {
    ProcessBytesAndMyClassInstance(byteLists[i], myClassInstances[i]);
  }
} 

public void MethodTakesIEnumerable(IEnumerable<MyClass> myClassInstances) {
  List<List<byte>> byteLists = GetByteLists(myClassInstances.Count());
  int i = 0;
  foreach(MyClass instance in myClassInstances) {
    ProcessBytesAndMyClassInstance(byteLists[i], instance);
    i++;
  }
}

В this В статье говорится, что «я всегда должен использовать тот тип, который предоставляет контракт только для тех методов, которые вы действительно используете».Метод, который принимает IEnumerable, по-прежнему определяет индекс, который используется в цикле.Поскольку этот индекс будет указывать на действительную запись , если myClassInstances были списком , значит ли это, что я должен просто использовать метод, который принимает IList?Теперь у меня есть возможность использовать индексатор IList.Или, поскольку существует решение, которое принимает IEnumerable , следует ли мне использовать это, поскольку оно поддерживает наибольшее количество входов?

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

На вашем месте я бы вдохновился тем, как Microsoft внедрила LINQ. Многие операторы, которые могут извлечь выгоду из возможности использовать тип коллекции, все еще имеют IEnumerable<TSource> в качестве исходных данных, но они просто пытаются привести к ICollection<TSource>, чтобы получить прямой доступ к индексированию и другим свойствам.

Взять (это слегка модифицировано) Count, например:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    ICollection<TSource> collection = source as ICollection<TSource>;
    if (collection != null)
    {
        return collection.Count;
    }
    ICollection collection2 = source as ICollection;
    if (collection2 != null)
    {
        return collection2.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num = checked(num + 1);
        }
        return num;
    }
}

Если тип ввода можно преобразовать в коллекцию, тогда оператор Count просто возвращает счетчик; в противном случае он перебирает список.

Таким образом, вы получаете лучшее из обоих типов.

0 голосов
/ 11 апреля 2019

IEnumerable обычно безопасная ставка, если вы не уверены, как люди будут использовать API. Существует множество случаев, когда у пользователя не будет объекта IList, особенно при использовании вещей из Linq, в дополнение к любым другим коллекциям, кроме списков, таким как LinkedList или Queue.

Например, если они делают someList.Select((x) => new OtherThing(x, "test")), фильтруют с Where и т. Д., Тогда они получат IEnumerable. Хотя в System.Linq есть также удобное myEnumerable.ToList(), это дополнительное преобразование, которое им придется выполнять, и оно оказывает некоторое влияние на производительность, возможно, хуже, чем то, которого вы надеялись избежать.

Конечно, бывают случаи, когда из соображений производительности предпочтительнее использовать другие типы, особенно когда имеешь дело с большими объемами небольших значений (например, byte[]), или упрощаешь реализацию, например, для произвольного доступа или изменения данных.

Вы должны учитывать компромиссы самостоятельно, хотя вы можете черпать вдохновение из стандартных классов и других популярных библиотек для языка. Для публичных библиотек вы также должны быть очень осторожны при рассмотрении бинарной совместимости, например, если вы возвращаете IEnumerable, тогда вы можете изменить свою реализацию, чтобы использовать другой фактический тип, если вы возвращаете List или даже IList затем вы более ограничены в том, что технически возможно без нарушения совместимости.

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