可选参数,好还是坏?

问题描述 投票:6回答:4

我正在编写和浏览项目中的许多方法,并且我认为overloads很有用,我认为使用具有默认值的简单optional parameter可以解决编写问题更具可读性,我认为高效的代码。

现在我听说在方法中使用这些参数可能会带来讨厌的副作用。

这些副作用是什么,使用这些参数保持代码干净的风险值得吗?

vb.net c#-4.0 optional-parameters
4个回答
12
投票
我将通过说出

任何语言功能都可以很好地使用或使用不当的位置作为开头来回答我的问题。可选参数有一些缺点,就像像var那样声明局部变量还是泛型一样。

这些副作用是什么

两个想到。

首先是可选参数的默认值是嵌入在方法

consumer

中的编译时间常数。假设我在AssemblyA中有此类:public class Foo { public void Bar(string baz = "cat") { //Omitted } }
而这在AssemblyB中:

public void CallBar() { new Foo().Bar(); }

最终真正产生的是这个,在assemblyB中:

public void CallBar() { new Foo().Bar("cat"); }

因此,如果要更改Bar的默认值,则

both

assemblyA和assemblyB将需要重新编译。因此,如果方法使用可选参数,而不是内部方法或私有方法,则我倾向于不将它们声明为公共方法。如果需要将其声明为公共,则可以使用重载。第二个问题是它们如何与界面和多态性相互作用。使用此界面:

public interface IBar { void Foo(string baz = "cat"); }

和这个班级:

public class Bar : IBar { public void Foo(string baz = "dog") { Console.WriteLine(baz); } }

这些行将打印不同的内容:

IBar bar1 = new Bar(); bar1.Foo(); //Prints "cat" var bar2 = new Bar(); bar2.Foo(); //Prints "dog"

这些是我想到的两个负面因素。但是,也有积极的一面。考虑这种方法:

void Foo(string bar = "bar", string baz = "baz", string yat = "yat") { }

创建默认提供所有可能排列的方法将是几十行,甚至数十行代码。

结论:可选参数很好,可能很差。就像其他任何东西一样。


5
投票
我想说,这取决于您包含或省略该参数时方法的不同。

如果没有参数的方法的行为和内部功能有很大不同,请使其成为重载。如果您使用可选参数更改行为,请不要。而不是使用一种方法对一个参数做一件事情,而当您传入第二个参数时有所不同的方法,则要选择一种方法来做一件事情,而另一种方法则做另一件事。如果它们的行为相差很大,则它们可能应该完全分开,并且不要重载同一个名称。

如果需要知道参数是用户指定的还是空白的,请考虑使其成为重载。有时,如果要从中传递值的地方不允许使用空值,则可以使用可为空的值,但是通常您不能排除用户传递null的可能性,因此,如果您需要知道值的来源以及值的含义,请勿使用可选参数。

首先,请记住,可选参数(按定义应为kinda)应用于对方法的结果影响很小,无关紧要或不重要的事情。如果更改默认值,则在未指定值的情况下调用该方法的任何地方仍应对结果满意。如果更改默认值,然后发现调用可选参数保留为空的方法的其他代码现在不能正常工作,则可能不应该是可选参数。

可以使用可选参数的好地方是:

    如果未提供值,则可以安全地将某些内容设置为默认值的方法。基本上,这涵盖了呼叫者可能不知道或不在乎值是什么的所有内容。一个很好的例子是加密方法-调用者可能会认为“我不知道加密,我不知道R应该设置为什么值,我只是希望将其加密”,在这种情况下,您可以设置默认值明智的价值观。通常,这些方法以带有内部变量的方法开始,然后您将其移交给用户提供。当唯一的区别是一个方法的开始处有var foo = bar;时,使用两种方法毫无意义。
  • 具有一组参数的方法,但并非全部都需要。这在构造函数中很常见。您会看到重载,每个重载都设置了各种属性的不同组合,但是如果需要设置三个或四个参数,则可能需要很多重载才能覆盖所有可能的组合(基本上是握手问题),并且所有这些重载在内部或多或少具有相同的行为。您可以通过让大多数参数仅设置默认值并调用设置所有参数的参数来解决此问题,但是使用可选参数的代码更少。
  • 调用它们的编码人员可能想要设置参数的方法,但是您希望他们知道什么是“正常”值。例如,我们前面提到的加密方法可能需要各种参数来进行内部数学运算。编码人员可能会看到他们可以传入workFactorblockSize的值,但他们可能不知道这些值是什么“正常”值。注释和文档在这里会有所帮助,但可选参数也将有所帮助-编码器将在签名[workFactor = 24], [blockSize = 256]中看到,这有助于他们判断哪种值是明智的。 (当然,这不是没有正确注释和记录代码的借口。)

2
投票
您未编写更具可读性和效率的代码。

首先,您的方法签名将不必要地更长。

其次,重载并不仅仅出于使用默认值的目的-快速查看Convert类应该向您显示。很多时候,重载方法具有不同的执行路径,这将成为单个非重载方法中的意大利面条式代码。

第三,有时您需要知道是否将值用作输入。如果用户碰巧使用与您使用的默认值相同的值,那么您如何知道用户是否传递了这些值?


0
投票
[通常,我在C#中看到可选参数,例如IMyInterface parameter = null。特别是当我在构造函数中看到它时,我什至会说这是一种代码味道。我知道这是一个艰难的决定-但在这种情况下,它掩盖了您的依赖关系,这很糟糕。

就像vcsjones所说的那样,您可以正确使用这些语言功能,但我相信可选参数仅应在某些情况下使用。

我的看法。

© www.soinside.com 2019 - 2024. All rights reserved.