Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# method with default parameter value does not generate overload without parameter?

Tags:

c#

Recently, I wanted to add an optional parameter to an extension method. The original method looked like this:

public static class Extensions {
    public static bool Foo(this IFoo target) {
        target.DoIt(true);
    }
}

This is obviously a simplified version but let's go from that.

What I did is:

public static class Extensions {
    public static bool Foo(this IFoo target, bool flag = true) {
        target.DoIt(flag);
    }
}

All I did is introduce an optional parameter with a default value, right? What I was expecting was the compiler to generate the overloaded method, without the flag. This partially happened. Any code that I recompiled was able to compile and execute without any problems, even without the parameter like this:

...
IFoo foo = new FooBar();
foo.Foo();
...

However, any code that was built against the previous version of Foo() did not work, throwing the following exception:

Unhandled Exception: System.MissingMethodException: Method not found: 'Boolean Models.Class1.Foo()'.
at DefaultParamsTests.Program.Main(String[] args)

This is obviously a problem for us as we do have a public API that our customers do leverage and this would be a breaking change.

The solution is to explicitly create an overload:

public static class Extensions {
    public static bool Foo(this IFoo target) {
        target.DoIt(true);
    }

    public static bool Foo(this IFoo target, bool ) {
        target.DoIt(true);
    }
}

However, Resharper does suggest that I could introduce an optional parameter for method foo.

resharper introduce optional parameter

If I do follow the refactoring it basically does what I showed above. However, that won't work for existing code.

resharper refactored

I have looked at the generated IL using both Reflector and dotPeek. Neither is showing the generation of the overload.

What am I missing?

like image 937
Eric Liprandi Avatar asked Jan 28 '15 04:01

Eric Liprandi


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.


2 Answers

In the case of default parameters, the actual call site is re-written to use the default value. This means an overload isn't generated at all, your calling code is modified!

public void fun(int x = 3) { }

// in another file
fun();   // compiler re-writes to fun(3);
fun(7);  // fun(7) as expected

// actual code generated by the c# compiler
fun(3);
fun(7);

If you use optional parameters in C# you need to re-compile all callers when the function changes. For this reason it is strongly discouraged to put these kind of methods on a public interface (e.g. called by other's code). Using them inside your own linked projects is fine, since they should all compile at the same time

like image 145
Andrew Avatar answered Sep 27 '22 20:09

Andrew


Optional parameters in methods in C# are resolved at compile-time at the call site. Your calling code that omits the parameter expands to include the parameter, calling the two-parameter version. This is the opposite of what you are presuming happens, with creating an overload.

like image 27
maxwellb Avatar answered Sep 27 '22 20:09

maxwellb