C# Optional Parameters or Method Overload? [duplic

2019-02-07 20:40发布

问题:

This question already has an answer here:

  • method overloading vs optional parameter in C# 4.0 [duplicate] 11 answers

Since C# added optional parameters is it considered a better practice to use optional parameters or method overloads or is there a particular case where you would want to use one over the other. i.e a function w/ lots of parameters would be better suited w/ optional parameters?

回答1:

Optional parameters are nice, but should be used when it makes sense. Optional parameters often muddy the intent of the method -- If there is another alternative I would lean towards the alternative.

Part of the need for optional parameters and named parameters is because COM allowed optional and name parameters:

MSDN

Some APIs, most notably COM interfaces such as the Office automation APIs, are written specifically with named and optional parameters in mind. Up until now it has been very painful to call into these APIs from C#, with sometimes as many as thirty arguments having to be explicitly passed, most of which have reasonable default values and could be omitted.

SomeNewKid from forums.asp.net puts succinctly:

http://forums.asp.net/t/386604.aspx/1

...overloaded methods are generally preferable to optional parameters. Why? To keep each of your methods clear in purpose. That is, each method should do one thing well. As soon as you introduce optional parameters, you are diluting the cleanliness of that method, and introducing branching logic that is probably best kept out of a method. This clarity of purpose becomes even more important when you start using inheritance. If you override a method that has one or more optional parameters, they become harder to work with. So, I'd suggest that for anything other than quick and dirty classes, you use overloading in preference to optional parameters.

Keep in mind that optional parameters are a syntactical sugar:

Reflector 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 
    }

}


回答2:

Code Analysis in Visual Studio and FxCop recommends you do not use optional arguments in public APIs (rule CA1026: Default parameters should not be used). The reason given is that not all .NET languages support them.

I think a better reason to avoid them though, is that they can introduce either runtime or compile-time problems if you add more overloads in a version 2.0 of your API. Phil Haack explains here.

I'm going to adopt Phil's conclusion: Optional parameters were designed to support COM interop; if you're not using COM, leave them alone.



回答3:

I'm not sure there's a canonical answer for this - it's subjective and case-by-case. However, in my opinion optional parameters create more explicit APIs and therefore, I generally prefer them over method overloads.

Specifically, when working with Intellisense I much prefer to see this:

Over this:

Where I may have to guess (or look up documentation) for what the value of param1 and param2 will be if I don't specify.



回答4:

Optional parameters are meant to facilitate COM object interactions as COM objects use lots of optional parameters. So if you're doing P/Invoke or COM object stuff, prefer optional parameters. Otherwise, method overloading is the proper way to go as it saves a lot of confusion.



回答5:

Rather than overloading or named optional parameters, I've grown to like object initializers very much. All you need in the class is a parameterless constructor, and public properties for anything you want to set on initialization.

Assuming class Bar has public string properties "Name" and "Pet", you can construct a new object like this.

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

The advantage is that you don't need a separate overload for each combination of values that you want to initialize.



回答6:

Optional parameters require a default value (I only assume), and thus in some cases it might be difficult to supply one. Why? Well some classes need runtime information to get initialized which may not be available to the compiler.

When it comes to primitive types, the answer may have to do with if a default value can be assumed, or if the absence of a parameter might signify different behavior by the method.