限制每种方法的参数数量?
假设参数类型相同,那么方法的参数数量是否有经验法则? 我只是想知道我应该在哪里绘制线和我的替代品(即接口,数组等)。
我会说这真的取决于你的情况。 你在为整套做些什么吗? 例如,validation所有项目或聚合数据? 在这种情况下,我会将IEnumerable作为单个参数传递。
传递很多参数可能是关注点分离不好的一个好兆头(即你的方法做得太多了),但听起来好像在这种情况下,你传递一组定义明确的项目以某种方式迭代它们。 给定C#3中的集合初始化器语法,我会在几乎所有情况下推荐IEnumerable,这些参数列表类似于Type a, Type b, Type c...
当然,如果您的参数实际上被区别对待,那么将它们分开是有意义的,但我会考虑您在这种情况下正在做什么。 想到的一个简单案例是构建树数据结构并具有构建节点子节点的function。 语法不佳可能是:
Node BuildTree( Node parent, Node child1, Node child2...)
我可能会追求更像:
void ConstructChildren( this Node parent, IEnumerable children)
但是,如果您可以提供有关您的案例的更多信息,以及您对参数执行的逻辑类型,则可能更容易看出它是否是折叠或重构的良好候选者。
史蒂夫麦康奈尔在Code Complete中解决了这一问题,理由是研究表明人们一次无法真正处理超过七个信息块,在任何实际情况下都会使这七个信息成为常识。
在该节的结论段落(第二版第178页)中,他写道:
如果你发现自己经常传递多个参数,那么例程之间的耦合就太紧了……如果要将相同的数据传递给许多不同的例程,请将例程分组到一个类中,并将常用数据视为类数据。
我试着把它限制在4左右。 有人说少说,有些人说更多。
大量参数的替代方法是创建一个操作类,即替换:
func(boo, far, lint, pizza, flags);
同
var action = new DoSomethingObject(boo, far, lint); action.Food = pizza; action.Go(flags);
这比function有一些优点:
- 如果某些参数是可选的,您可以将它们公开为属性(例如上面的
pizza
)。 - 如果你的函数接受了那么多参数,那么很可能它会做很多事情,并且可以分解成更小的函数。 一堂课帮助你干净利落地完成这项工作。
如果您将传递未知数量的参数,则应使用varargs或传递IEnumerable。 当然,有时你会传递相同类型的固定数量的项目。 在后一种情况下,固定数字应遵循方法的目的。
此外,为了获得更好的呼叫站点可读性,您可以使用params参数列表(之前提到的varargs),而不是
void ConstructChildren( Node parent, IEnumerable children) .... List children = new List {child1, child2, child3}; ConstructChildren(parent, children);
我会用
void ConstructChildren( Node parent, params Node[] children) ... ConstructChildren( parent, child1, child2, child3);
但是,如果在子集合中使用更多5-6-7个项目,则params语法会变得难看。