由于C#添加了可选参数,因此使用可选参数或方法重载被认为是更好的做法,或者是否存在您希望使用其中一个的特定情况。即具有大量参数的函数更适合w /可选参数?
答案 0 :(得分:19)
可选参数很好,但应该在有意义时使用。可选参数通常会使方法的意图变得混乱 - 如果有另一种选择,我会倾向于替代方案。
可选参数和命名参数的部分需求是因为COM允许可选参数和名称参数:
<强> MSDN 强>
来自forums.asp.net的SomeNewKid简明扼要地说:一些API,最着名的是COM接口 例如Office自动化API, 是专门写的命名 和可选参数。向上 直到现在它已经非常痛苦 从C#调用这些API,用 有时多达三十个论点 必须明确地通过,大多数 其中有合理的默认值 值,可以省略。
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
}
}
答案 1 :(得分:11)
Visual Studio和FxCop中的代码分析建议您不要在公共API中使用可选参数(规则CA1026: Default parameters should not be used)。给出的理由是并非所有.NET语言都支持它们。
我认为避免它们的一个更好的理由是,如果在API的2.0版本中添加更多重载,它们可能会引入运行时或编译时问题。 Phil Haack explains here
我将采用Phil的结论:可选参数旨在支持COM互操作;如果你不使用COM,请不要管它们。
答案 2 :(得分:10)
我不确定这是否有规范的答案 - 这是主观的,逐案的。但是,在我看来,可选参数创建了更明确的API,因此,我通常更喜欢它们而不是方法重载。
具体来说,在使用Intellisense时,我更喜欢看到这个:
通过这个:
如果我没有指定,我可能需要猜测(或查找文档)param1和param2的值。
答案 3 :(得分:4)
可选参数用于促进COM对象交互,因为COM对象使用大量可选参数。因此,如果您正在进行P / Invoke或COM对象,则首选可选参数。否则,方法重载是正确的方法,因为它可以节省很多混乱。
答案 4 :(得分:4)
我没有重载或命名可选参数,而是非常喜欢对象初始化器。您在类中所需要的只是一个无参数构造函数,以及您希望在初始化时设置的任何内容的公共属性。
假设类Bar具有公共字符串属性“Name”和“Pet”,您可以构造一个这样的新对象。
var foo = new Bar { Name = "Fred", Pet = "Dino" };
优点是您不需要为要初始化的每个值组合单独重载。
答案 5 :(得分:1)
可选参数需要一个默认值(我只假设),因此在某些情况下可能很难提供一个。为什么?好吧,有些类需要运行时信息才能初始化,编译器可能无法使用。
当涉及到原始类型时,答案可能与假设一个默认值有关,或者如果缺少一个参数可能表示该方法的不同行为。