我正在编写和浏览项目中的许多方法,并且我认为overloads
很有用,我认为使用具有默认值的简单optional parameter
可以解决编写问题更具可读性,我认为高效的代码。
现在我听说在方法中使用这些参数可能会带来讨厌的副作用。
这些副作用是什么,使用这些参数保持代码干净的风险值得吗?
任何语言功能都可以很好地使用或使用不当的位置作为开头来回答我的问题。可选参数有一些缺点,就像像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");
}
因此,如果要更改assemblyA和assemblyB将需要重新编译。因此,如果方法使用可选参数,而不是内部方法或私有方法,则我倾向于不将它们声明为公共方法。如果需要将其声明为公共,则可以使用重载。第二个问题是它们如何与界面和多态性相互作用。使用此界面:Bar
的默认值,则both
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")
{
}
创建默认提供所有可能排列的方法将是几十行,甚至数十行代码。结论:可选参数很好,可能很差。就像其他任何东西一样。
如果没有参数的方法的行为和内部功能有很大不同,请使其成为重载。如果您使用可选参数更改行为,请不要。而不是使用一种方法对一个参数做一件事情,而当您传入第二个参数时有所不同的方法,则要选择一种方法来做一件事情,而另一种方法则做另一件事。如果它们的行为相差很大,则它们可能应该完全分开,并且不要重载同一个名称。
如果需要知道参数是用户指定的还是空白的,请考虑使其成为重载。有时,如果要从中传递值的地方不允许使用空值,则可以使用可为空的值,但是通常您不能排除用户传递null
的可能性,因此,如果您需要知道值的来源以及值的含义,请勿使用可选参数。
首先,请记住,可选参数(按定义应为kinda)应用于对方法的结果影响很小,无关紧要或不重要的事情。如果更改默认值,则在未指定值的情况下调用该方法的任何地方仍应对结果满意。如果更改默认值,然后发现调用可选参数保留为空的方法的其他代码现在不能正常工作,则可能不应该是可选参数。
可以使用可选参数的好地方是:
var foo = bar;
时,使用两种方法毫无意义。workFactor
或blockSize
的值,但他们可能不知道这些值是什么“正常”值。注释和文档在这里会有所帮助,但可选参数也将有所帮助-编码器将在签名[workFactor = 24], [blockSize = 256]
中看到,这有助于他们判断哪种值是明智的。 (当然,这不是没有正确注释和记录代码的借口。)首先,您的方法签名将不必要地更长。
其次,重载并不仅仅出于使用默认值的目的-快速查看Convert类应该向您显示。很多时候,重载方法具有不同的执行路径,这将成为单个非重载方法中的意大利面条式代码。
第三,有时您需要知道是否将值用作输入。如果用户碰巧使用与您使用的默认值相同的值,那么您如何知道用户是否传递了这些值?
IMyInterface parameter = null
。特别是当我在构造函数中看到它时,我什至会说这是一种代码味道。我知道这是一个艰难的决定-但在这种情况下,它掩盖了您的依赖关系,这很糟糕。就像vcsjones所说的那样,您可以正确使用这些语言功能,但我相信可选参数仅应在某些情况下使用。
我的看法。