Какой тип коллекции должен принимать метод .Net, перечисляющий несколько раз в качестве параметра? - PullRequest
2 голосов
/ 08 апреля 2019

У меня есть простой метод, подобный этому:

private void CalculateTotals(IEnumerable<MyData> data)
{
   decimal value1 = data.Sum(d => d.Value1);
   decimal value2 = data.Sum(d => d.Value2);
}

Это работает и позволяет передавать любой тип коллекции, но это также выполнит многократное перечисление данных, которое может быть довольно дорогостоящим, так какЧто ж.

Теперь я могу изменить тип параметра на ICollection<MyData>, но это будет означать, что вызывающая сторона не знает, может ли метод изменить / изменить коллекцию, поскольку для нее можно вызвать Add/Remove.

Мое следующее предположение - IReadonlyCollection<MyData>, которое кажется наиболее подходящим, но это будет означать, что каждый вызывающий абонент должен будет создать / преобразовать в новый ReadonlyCollection.

Существуют ли какие-либо "предпочтительные" способырешения этого в .Net?

Ответы [ 4 ]

5 голосов
/ 08 апреля 2019

Мое следующее предположение - IReadonlyCollection<MyData>, которое кажется наиболее подходящим, но это будет означать, что каждый вызывающий абонент должен будет создать / преобразовать в новый ReadonlyCollection.

Ну, нет, потому что различные встроенные типы реализуют этот интерфейс :

Но вместо этого вы можете предотвратить двойное перечисление.

3 голосов
/ 08 апреля 2019

В общем, я бы предложил использовать наименее жадный интерфейс, который соответствует вашим потребностям.Так что, если ваш метод должен повторяться, просто используйте самый общий, который является IEnumerable<T>.Если вам нужно добавить / удалить, используйте ICollection, если вам нужен индексный доступ, используйте IList.

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

Лучше всего также проверить, материализована ли ваша коллекция уже , материализованная путем приведения к списку или массиву сначала:

var dataAsList = (data as IList<T>) ?? data.ToList();
3 голосов
/ 08 апреля 2019

Это дает вам одно перечисление:

private void CalculateTotals(IEnumerable<MyData> data)
{
    (decimal value1, decimal value2) =
        data.Aggregate((0m, 0m), (a, x) => (a.Item1 + x.Value1, a.Item2 + x.Value2));
}
0 голосов
/ 08 апреля 2019

Вы должны сложить.У вас есть коллекция.Вы должны перечислить.

Конец истории.

Итак, IEnumerable отлично работает.

...