C#可选参数或方法重载?

时间:2011-05-25 23:12:06

标签: c# coding-style overloading optional-parameters

由于C#添加了可选参数,因此使用可选参数或方法重载被认为是更好的做法,或者是否存在您希望使用其中一个的特定情况。即具有大量参数的函数更适合w /可选参数?

6 个答案:

答案 0 :(得分:19)

可选参数很好,但应该在有意义时使用。可选参数通常会使方法的意图变得混乱 - 如果有另一种选择,我会倾向于替代方案。

可选参数和命名参数的部分需求是因为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 
    }

}

答案 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时,我更喜欢看到这个:

optional params with defaults

通过这个:

overload 1

overload 2

overload 3

如果我没有指定,我可能需要猜测(或查找文档)param1和param2的值。

答案 3 :(得分:4)

可选参数用于促进COM对象交互,因为COM对象使用大量可选参数。因此,如果您正在进行P / Invoke或COM对象,则首选可选参数。否则,方法重载是正确的方法,因为它可以节省很多混乱。

答案 4 :(得分:4)

我没有重载或命名可选参数,而是非常喜欢对象初始化器。您在类中所需要的只是一个无参数构造函数,以及您希望在初始化时设置的任何内容的公共属性。

假设类Bar具有公共字符串属性“Name”和“Pet”,您可以构造一个这样的新对象。

var foo = new Bar { Name = "Fred", Pet = "Dino" };

优点是您不需要为要初始化的每个值组合单独重载。

答案 5 :(得分:1)

可选参数需要一个默认值(我只假设),因此在某些情况下可能很难提供一个。为什么?好吧,有些类需要运行时信息才能初始化,编译器可能无法使用。

当涉及到原始类型时,答案可能与假设一个默认值有关,或者如果缺少一个参数可能表示该方法的不同行为。