2017-01-08 2 views
2

Часто предлагая методы, которые принимают массив, можно оптимизировать, чтобы принимать более общие классы, которые являются как IEnumerable, так и требуют Count или Length.Какой тип параметра предоставить IEnumerable и имеет счет?

Пример:

public static T NextObject<T>(this Random random, T[] array) 
{ 
    return array[random.Next(array.Length)]; 
} 

Здесь я использую Array, чтобы получить конкретный элемент, зная количество элементов. Какой класс оптимален для этого в общем?

  • IList
  • ICollection - также имеет Count
  • другой интерфейс или класс или набор различных интерфейсов?

Я думаю , IEnumerable не может быть хорошей идеей, потому что Count() может вызвать побочные эффекты на производительность, если основной Перечислитель является более сложным.

+0

Я предлагаю использовать 'ICollection ', но я думаю, что это немного * основанное на мнениях *. – MarcinJuraszek

+0

'ICollection ' не имеет индексатора. Я думаю, что и это, и 'Array' как две перегрузки могут * (не уверены) * охватывать все типы. Я не думаю, что это мнение основано, потому что вопрос в основном охватывает все распространенные типы с наименьшими перегрузками. – bytecode77

+0

Почему нет простого списка ? –

ответ

2

Вам нужны элементы доступа по индексу и количеству элементов в коллекции. Вы также хотите меньше дополнительные члены в области сбора/интерфейсе

     | IList<T> | ICollection<T> | IEnumerable<T> | T[] 
Access by index  |  + |  -  |  -  | + 
Count of items  |  + |  +  |  -  | + 
Less unwanted members |  - |  +  |  +  | ~ 

Как вы можете видеть, ICollection и IEnumerable не соответствуют вашим потребностям. Я не вижу большой разницы между выбором IList или массива. IList может быть более легким, чем массив, но у него много ненужных операций (Add, Remove, Clear), а с помощью массива вы можете использовать params, что очень удобно.

+0

Очень хорошая визуализация! Поэтому, вероятно, было бы лучше перегрузить как массив, так и IList ... Но что, если код более сложный, чем в примере? Предоставление только массива и требование '.ToArray' в методе потребления? – bytecode77

+0

@ bytecode77 вероятно две перегрузки с 'IList ' и 'params T []' были бы наиболее удобной опцией: 'ranomd.NextObject (apple, banana, peach)' выглядит хорошо –

0

Ваш метод должен принимать наименее специфический тип, который удовлетворяет потребностям метода. Возможно достижение наименьшей возможной связи. Вот подпись для ICollection

public interface ICollection<T> : IEnumerable<T>, IEnumerable 

Поскольку поддержки ни ICollection<T>, ни IEnumerable<T> индексации, то никто не будет работать.

Массив слишком специфичен, но List<T> или IList<T> удовлетворит ваши потребности, так как вам необходим доступ по индексу. В противном случае клиентам (потребителям класса) необходимо будет присвоить тип массива.

Но счет может вызвать побочные эффекты на производительность

Count() является метод расширения System.Linq.Enumerable. Он будет пытаться использовать типы, поддерживающие O (1), такие как ICollection (свойство Count). Если ни один из них не доступен, он будет перемещать все предметы и считать их, что становится O (N).

+0

Если я не ошибаюсь, это даже * все классы коллекции, реализующие 'IEnumerable '. Но поскольку он не поддерживает произвольный доступ и использование '.Skip' имеет неопределенный компактный результат, IEnumerable нельзя использовать. – bytecode77

+0

@ bytecode77 извините, что ваш вопрос касался количества и длины, но теперь я вижу, что ваш код требует случайной индексации. Отредактировал ответ. – CodingYoshi

Смежные вопросы