как определиться с подписью API - PullRequest
4 голосов
/ 02 марта 2011

Много раз при написании функций, принимающих перечислимые типы, я сталкиваюсь с этой путаницей.Какой из представленных API будет лучше из следующих опций:

public void Resolve(Func<bool>[] howtos)

public void Resolve(IEnumerable<Func<bool>> howtos)

public void Resolve(List<Func<bool>> howtos)

Я обычно решаю, основываясь на следующем: если необходимо изменить ввод путем добавления или удаления элементов, тогда используйте List, иначе используйте IEnumerable.Не уверен насчет опции Array.

Существуют ли другие моменты, которые необходимо учитывать при принятии решения о показе API?Есть ли эмпирическое правило, в котором четко определены ситуации, в которых следует отдавать предпочтение другим?

Спасибо

Ответы [ 3 ]

4 голосов
/ 02 марта 2011

Вы должны всегда принимать наименее ограничивающие типы параметров.

Это означает IEnumerable<T>, ICollection<T> или IList<T>.
Таким образом, клиент может свободно передавать любые реализациинапример, массив, HashSet<T> или ReadOnlyCollection<T>.

В частности, вы должны взять IEnumerable<T>, если вам нужно только итерировать данные, ICollection<T>, если вы также хотите добавить или удалитьэлементы, или если вам нужно знать размер, и IList<T>, если вам нужен произвольный доступ (индексатор).

2 голосов
/ 02 марта 2011

Основным фактором для меня при принятии этого решения является

Что на самом деле делает Resolve с коллекцией?

Если Resolve не изменяет коллекцию каким-либо образом, я бы предпочел подпись IEnumerable<Func<bool>>. Он учитывает наибольшее количество вариантов использования и наиболее точно выражает намерение API. Я бы, например, предположил, что что-либо, принимающее более конкретный тип, такой как List<T>, намеревалось изменить переданную коллекцию. Наблюдение IEnumerable<T> дает мне некоторую уверенность в том, что коллекция просто перечисляется.

Если Resolve изменяет коллекцию, я бы предпочел, чтобы подпись List<T> указывала, что мутация действительно возможна. Возможно, я бы создал свободный интерфейс, взяв и вернув IEnumerable<T>. Который будет во многом зависеть от типа метода Resolve. Трудно обобщать, когда я бы выбрал одно над другим.

1 голос
/ 02 марта 2011

Ваш путь звучит хорошо. Единственное, что я хотел бы изменить, это иметь значение IList<T> вместо List<T>. Разрешение пользователю, например, проверять все, что вы добавляете в список.

...