Сигнатура метода, принимающего/возвращающего в качестве параметра список/массив?

У меня иногда встает вопрос - как лучше написать:

System.Collections.IList Get()
{
    return new object[] { };
}

System.Collections.ICollection Get()
{
    return new object[] { };
}

System.Collections.IEnumerable Get()
{
    return new object[] { };
}

object[] Get()
{
    return new object[] { };
}


Есть какая-нибудь разница, что использовать?
Есть ли разница в быстродействии?
Или лучше использовать в зависимости от контекста, что удобнее для дальнейшей работы?
Аналогичный вопрос и для аргументов метода.
  • Вопрос задан
  • 3045 просмотров
Решения вопроса 1
Vadimyan
@Vadimyan
Программист C#
Доброго дня.
Нужно выбирать действительно необходимый вам возвращаемый тип. С IEnumerable есть некоторые тонкости, которые необходимо знать и всегда о них помнить. Очень советую обе статьи, еще немного информации о коллекциях есть здесь. Я попробую уместить в паре строк основные правила.

IEnumerable(T) нужно возвращать только в случаях, когда клиент готов принять итератор, потенциально бесконечный! Фактически, этот интерфейс не стоит использовать почти никогда.
IReadOnlyCollection(T) нужно возвращать (и передавать в методы) в случаях, когда клиент пользуется данными коллекциями, но не должен изменять их. В большинстве случаев это именно так, можно сказать, что IReadOnlyCollection используется чаще остальных.
IList(T) и ICollection(T) возвращаются в случае, когда клиенту может понадобиться изменить коллекцию, добавив или удалив элементы. Такие ситуации встречаются крайне редко. Различие в том, что в случае с IList(T) клиент может обращаться к элементу по индексу. Что касается передачи этих интерфейсов в качестве аргумента метода, то это может понадобиться, когда метод модифицирует коллекцию, например, удаляет дублирующиеся элементы или очищает коллекцию от старых данных. Здесь есть выбор между явной работой с коллекцией или же передачей IReadOnlyCollection(T) и возвращением результата того же типа. Зависит от задачи.

Я бы сказал, что IReadOnlyCollection(T) наиболее предпочтителен в качестве возвращаемого параметра, поскольку при таком подходе код остаётся структурированным - можно быть уверенным, что возвращаемая коллекция не модифицируется ниже по коду.

p.s. Ах да, напоследок. У вас приведены примеры нетипизированных коллекций, которые медленнее их generic-собратьев из-за упаковки-распаковки. Ими пользоваться стоит только в крайний случаях, пример которым я наспех даже и не приведу.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@Free_ze
Пишу комментарии в комментарии, а не в ответы
Для аргумента - IEnumerable, если тебе нет необходимости в каких-то специфических методах. Его все контейнеры реализуют. Если же есть такая необходимость, то лучше принимать максимально "широкий" тип, который тебя устраивает.

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

В общем, пользоваться всеми благами ковариантности и контрвариантности, если таргет-платформа позволяет это (контрвариантность - с C#4.0 и .Net Framework 4, ковариантность - изначально).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы