2

I wonder if I should be using optional parameters in C#. Until now I was always overloading methods. But optional parameters are nice too, cleaner and less code. And I use them in other languages so I'm also used to them in some way. Is there anything that speaks against using them ? Performance is the first key point for me. Would it drop ?


Example code:
class Program
{
    // overloading
    private static void test1(string text1)
    {
        Console.WriteLine(text1 + " " + "world");
    }

    private static void test1(string text1, string text2)
    {
        Console.WriteLine(text1 + " " + text2);
    }

    // optional parameters
    private static void test2(string text1, string text2 = "world")
    {
        Console.WriteLine(text1 + " " + text2);
    }

    static void Main(string[] args)
    {
        test1("hello");
        test1("hello", "guest");

        test2("hello"); // transforms to test2("hello", "world"); ?
        test2("hello", "guest");

        Console.ReadKey();
    }
}


I measured the time needed for a few millions overload calls and optional parameter calls.
  • optional parameters with strings: 18 % slower (2 parameters, release)
  • optional parameters with ints: <1 % faster (2 parameters, release)

(And maybe compilers optimize or will optimize those optional parameter calls in future ?)

Ender Look
  • 2,303
  • 2
  • 17
  • 41
Bitterblue
  • 13,162
  • 17
  • 86
  • 124
  • Perf question on overloading answered in http://stackoverflow.com/questions/3581747/method-overloading-good-or-bad-design – Aron Oct 25 '13 at 07:18
  • possible duplicate of [method overloading vs optional parameter in C# 4.0](http://stackoverflow.com/questions/3316402/method-overloading-vs-optional-parameter-in-c-sharp-4-0) – Aron Oct 25 '13 at 07:19

2 Answers2

3

I just did a quick test and the compiler optimizes the code. This basic example Main method.

public static void OptionalParamMethod(bool input, string input2 = null)
{
}

public static void Main(string[] args)
{
    OptionalParamMethod(true);
    OptionalParamMethod(false, "hello");
}

Compiles to this so the optional params are filled in by the compiler.

public static void Main(string[] args)
{
    OptionalParamMethod(true, null);
    OptionalParamMethod(false, "hello");
}

As for performance you could argue optional parameters have a slight advantage as there is only a single method call rather than chained method calls like you would normally have for an overloaded method. The code below is compiled output to show what I am talking about. The difference is quite academic though and I doubt you would ever notice in practice.

public static void Main(string[] args)
{
    OptionalParamMethod(true, null);
    OptionalParamMethod(false, "hello");
    OverloadParamMethod(true);
    OverloadParamMethod(false, "hello");
}

public static void OptionalParamMethod(bool input, [Optional, DefaultParameterValue(null)] string input2)
{
    Console.WriteLine("OptionalParamMethod");
}

public static void OverloadParamMethod(bool input)
{
    OverloadParamMethod(input, null);
}

public static void OverloadParamMethod(bool input, string input2)
{
    Console.WriteLine("OverloadParamMethod");
}
David Ewen
  • 3,632
  • 1
  • 19
  • 30
  • Can you tell me how do you view the optimized code ? And this looks like a performance drop to me. Is it ? – Bitterblue Oct 25 '13 at 06:55
  • [Reflector](http://www.red-gate.com/products/dotnet-development/reflector/) lets you view the compiled code. There is no performance drop it compiles out to be the same as any normal method call. PS this was a Debug build if it was a Release build then the compiler would actually have removed the method calls entirely as the method is a NOP. – David Ewen Oct 25 '13 at 07:00
  • But when you call an overloaded method with 1 parameter, 1 object is sent. When you call an optional parameter method with 2 parameters and optimized code sends all parameters (with defaults) more stack space is used and it takes more time to copy values and references. – Bitterblue Oct 25 '13 at 07:07
  • Just added more to answer. Normally you use optional params where you would do method chaining with overloaded methods. If this isn't what you are trying to achieve then you need to assess each case on it's own merits but in the general sense optional params probably win for performance. – David Ewen Oct 25 '13 at 07:11
  • 1
    -1 There is no performance hit due to either overloading nor optional parameters (at runtime). http://stackoverflow.com/questions/3581747/method-overloading-good-or-bad-design – Aron Oct 25 '13 at 07:17
  • @Aron there is a [very real yet very minor](https://gist.github.com/iwantedue/7150746) performance advantage to optional parameters at runtime. I am in no way suggesting anyone ever use either method for performance reasons like I said it's an academic difference. – David Ewen Oct 25 '13 at 07:30
  • Disagree. The performance is not DUE to the overloading but it because the implementation is done by calling the OTHER overload. There are performance issues with optional parameters which are not legal literals as well, which you completely glossed over. – Aron Oct 25 '13 at 07:41
  • I specifically mentioned chained method calls which is how most overloading is implemented and in that case there is a difference. – David Ewen Oct 25 '13 at 07:45
  • @ David and @Aron I tried David's code. None of you is wrong. But chained calls is what you do with your method. In my opinion the methods must do perfectly the same to be comparable. So if you remove the chain calls and counter++ instead, you get optional parameters being <2 % slower than overload. I'd say it doesn't matter and I'll go for what I like most. – Bitterblue Oct 25 '13 at 08:34
3

Neither overloading nor optional parameters will in themselves cause any changes in performance. As David Ewen noted, the C# compiler produces IL that does not know about optional parameters (this is the sources of some versioning bugs that come from optional parameters on types which can be literal).

As for overloading. C# is a (mostly) statically typed language. The compiled code directly references the address of the appropriate method. There is a small performance hit when overloading AT COMPILE time. In C++ in fact, overloading is done by a process called "name mangling" where each overload at compile time is given a unique name.

However there are cases where overloading CAN impact performance. But these are pretty obvious, like during reflection and in dynamic typed code.

It sounds like you are confused about the performance hit of virtual/abstract functions. In order for the .net runtime to resolve the correct function, there is an extra step which looks up the particular type's implementation of that method.

Aron
  • 15,464
  • 3
  • 31
  • 64