Предполагая, что все параметры одинаковы, существует ли правило большого пальца в отношении количества параметров для метода? Мне просто интересно, где я должен рисовать линию и какие мои альтернативы (т.е. интерфейс, массив и т.д.).
Ограничить количество параметров для каждого метода?
Ответ 1
Я бы сказал, это действительно зависит от вашего дела. Вы делаете что-то на весь набор? Проверять все элементы или агрегировать данные, например? В этом случае я передал бы IEnumerable как единственный параметр.
Передача множества параметров может быть хорошим признаком плохого разделения проблем (т.е. ваш метод делает слишком много), но похоже, что в этом случае вы проходите в четко определенном наборе элементов для их итерации каким-то образом. Учитывая синтаксис инициализатора коллекции в С# 3, я бы порекомендовал IEnumerable почти в каждом случае по списку параметров, которые были бы чем-то вроде Type a, Type b, Type c...
.
Конечно, если ваши параметры обрабатываются по-разному, то их разделение имеет смысл, но я бы подумал, что вы делаете в этом случае. Простым случаем, который приходит на ум, будет построение структуры данных дерева и функция для создания дочерних элементов node. Плохой синтаксис может быть:
Node BuildTree( Node parent, Node child1, Node child2...)
Я бы, вероятно, преследовал нечто большее:
void ConstructChildren( this Node parent, IEnumerable<Node> children)
Если вы можете предоставить более подробную информацию о своем деле, и какую логику вы выполняете по параметрам, вероятно, было бы легче увидеть, является ли это хорошим кандидатом для свертывания или рефакторинга.
Ответ 2
Стив Макконнелл обращается к этому в Code Complete, цитируя исследование, в котором говорится, что люди не могут обрабатывать более семи фрагментов информации за раз, делая семь пределов здравого смысла, где бы они ни практиковались.В заключительном абзаце этого раздела (стр. 178 во втором издании) он пишет:
Если вы окажетесь последовательно передавая несколько аргументов, связь между вашими подпрограммами тоже плотно... Если вы проходите то же самое данные для многих различных подпрограмм, группы подпрограммы в класс и лечение часто используемые данные как класс данных.
Ответ 3
Я пытаюсь ограничить его до 4 или около того. Некоторые люди говорят меньше, некоторые говорят больше.
Альтернативой тоннам параметров было бы создать класс операций, то есть заменить:
func(boo, far, lint, pizza, flags);
с
var action = new DoSomethingObject(boo, far, lint);
action.Food = pizza;
action.Go(flags);
Это имеет несколько преимуществ перед функцией:
- Если некоторые параметры являются необязательными, вы можете открыть их как свойства (например,
pizza
выше). - Если ваша функция принимает много аргументов, скорее всего, она многое делает и может быть разбита на более мелкие функции. Класс помогает вам сделать это чисто.
Ответ 4
Если вы пройдете неизвестное количество аргументов, вы должны использовать varargs или передать IEnumerable. Конечно, иногда вы передаете фиксированное количество элементов одного типа. В последнем случае фиксированное число должно следовать из цели метода.
Ответ 5
Кроме того, для большей читаемости сайта вы можете использовать список параметров params (ранее упомянутые varargs), поэтому вместо
void ConstructChildren( Node parent, IEnumerable<Node> children)
....
List<Node> children = new List<Node> {child1, child2, child3};
ConstructChildren(parent, children);
Я бы использовал
void ConstructChildren( Node parent, params Node[] children)
...
ConstructChildren( parent, child1, child2, child3);
Однако синтаксис params становится уродливым, если вы используете более 5-6-7 элементов в коллекции для детей.