限制每种方法的参数数量?

假设参数类型相同,那么方法的参数数量是否有经验法则? 我只是想知道我应该在哪里绘制线和我的替代品(即接口,数组等)。

我会说这真的取决于你的情况。 你在为整套做些什么吗? 例如,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语法会变得难看。