【发布时间】:2011-05-25 23:12:06
【问题描述】:
由于 C# 添加了可选参数,因此使用可选参数或方法重载被认为是一种更好的做法,或者是否存在您希望使用其中一个而不是另一个的特殊情况。即带有大量参数的函数更适合带有可选参数?
【问题讨论】:
标签: c# coding-style overloading optional-parameters
由于 C# 添加了可选参数,因此使用可选参数或方法重载被认为是一种更好的做法,或者是否存在您希望使用其中一个而不是另一个的特殊情况。即带有大量参数的函数更适合带有可选参数?
【问题讨论】:
标签: c# coding-style overloading optional-parameters
可选参数很好,但应该在有意义的时候使用。可选参数通常会混淆该方法的意图——如果有另一种选择,我会倾向于另一种选择。
之所以需要可选参数和命名参数,是因为 COM 允许使用可选参数和命名参数:
MSDN
一些 API,尤其是 COM 接口 例如 Office 自动化 API, 是专门用命名写的 和可选参数。向上 到现在为止一直很痛苦 从 C# 调用这些 API,使用 有时多达三十个参数 必须明确通过,大多数 其中有合理违约 值,可以省略。
来自 forums.asp.net 的 SomeNewKid 简洁地说:
http://forums.asp.net/t/386604.aspx/1
...重载的方法一般是 优于可选参数。 为什么?保持你的每一个方法 目的明确。也就是说,每种方法 应该做好一件事。立刻 你引入可选参数,你 正在稀释它的清洁度 方法,并引入分支 可能最好避开的逻辑 的一种方法。这种明确的目的 当你变得更加重要时 开始使用继承。如果你 覆盖具有一个或多个的方法 可选参数,它们变成 更难合作。所以,我建议 除了快速和 脏类,你使用重载 对可选参数的偏好。
请记住,可选参数是一种语法糖:
反射器 C#:
public class Class1
{
// Methods
public Class1()
{
this.Method1("3", "23");
}
public void Method1(string one, [Optional, DefaultParameterValue("23")] string two)
{
}
}
IL:
.class public auto ansi beforefieldinit Class1
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: call instance void [mscorlib]System.Object::.ctor()
L_0006: nop
L_0007: nop
L_0008: ldarg.0
L_0009: ldstr "3"
L_000e: ldstr "23"
L_0013: call instance void WebApplication1.Class1::Method1(string, string)
L_0018: nop
L_0019: nop
L_001a: ret
}
.method public hidebysig instance void Method1(string one, [opt] string two) cil managed
{
.param [2] = string('23')
.maxstack 8
L_0000: nop
L_0001: ret
}
}
【讨论】:
Visual Studio 和 FxCop 中的代码分析建议您不要在公共 API 中使用可选参数(规则 CA1026: Default parameters should not be used)。给出的原因是并非所有 .NET 语言都支持它们。
我认为避免它们的更好理由是,如果您在 API 的 2.0 版本中添加更多重载,它们可能会引入运行时或编译时问题。 Phil Haack explains here.
我将采纳 Phil 的结论:可选参数旨在支持 COM 互操作;如果您不使用 COM,请不要理会它们。
【讨论】:
我不确定是否有一个规范的答案 - 这是主观的和个案。但是,在我看来,可选参数会创建更明确的 API,因此,我通常更喜欢它们而不是方法重载。
具体来说,在使用 Intellisense 时,我更喜欢看到这个:
关于这个:
如果我不指定,我可能不得不猜测(或查找文档)param1 和 param2 的值。
【讨论】:
可选参数旨在促进 COM 对象交互,因为 COM 对象使用大量可选参数。所以如果你在做 P/Invoke 或 COM 对象的东西,更喜欢可选参数。否则,方法重载是正确的方法,因为它可以避免很多混乱。
【讨论】:
我已经非常喜欢对象初始化器,而不是重载或命名可选参数。在这个类中,你只需要一个无参数的构造函数,以及你想要在初始化时设置的任何东西的公共属性。
假设 Bar 类具有公共字符串属性“Name”和“Pet”,您可以像这样构造一个新对象。
var foo = new Bar { Name = "Fred", Pet = "Dino" };
优点是您不需要为要初始化的每个值组合单独重载。
【讨论】:
可选参数需要一个默认值(我只是假设),因此在某些情况下可能很难提供一个。为什么?有些类需要运行时信息才能初始化,而编译器可能无法使用这些信息。
对于原始类型,答案可能与是否可以假定默认值有关,或者是否缺少参数可能表示方法的不同行为。
【讨论】: