Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two methods that differ only in optional parameters [duplicate]

Tags:

c#

While digging in my company codebase i found something that astounds me: pairs of functions that differ only in optional parameters, here's one example:

public static List<AvailableDay> Find(string mailboxCalendarId, string[] typeTrameCles, DateTime dateMin, bool hasPhNonUrgent, bool hasPhUrgence, bool hasPhUrgenceDuJour)
public static List<AvailableDay> Find(string mailboxCalendarId, string[] typeTrameCles, DateTime dateMin, bool hasPhNonUrgent, bool hasPhUrgence, bool hasPhUrgenceDuJour, int maxDaysResultCout = 1)

what I find very strange, is that the compiler is happy with them. What is the explanation for this? Am I missing something?

like image 814
Souhaieb Besbes Avatar asked Dec 25 '15 15:12

Souhaieb Besbes


People also ask

What is the optional parameter?

Optional parameters are defined at the end of the parameter list, after any required parameters. If the caller provides an argument for any one of a succession of optional parameters, it must provide arguments for all preceding optional parameters.

How do you make a method parameter optional?

We can make a parameter optional by assigning default values for that parameter, like: public static void Sum(int a,int b , int[] n=null)

What are optional parameters are added?

Optional Parameters are parameters that can be specified, but are not required. This allows for functions that are more customizable, without requiring parameters that many users will not need.

Can we have multiple optional parameters in C#?

In c#, we can also achieve the optional parameters by using method overloading functionality. Generally, the method overloading functionality will allow us to create multiple methods with the same name but with different parameters.


2 Answers

This is perfectly valid code. In your situation, however, the optional parameter is never used, because the compiler will always prefer the first overload when the method is invoked with six parameters.

From C# In Depth:

When faced with a choice between a method which requires the compiler to fill in optional parameter values and one which doesn't, if the methods are otherwise "tied" (i.e. normal argument conversion hasn't decided a winner), overload resolution will pick the one where the caller has specified all the arguments explicitly.

There may be situations when the compiler would pick the first overload over the second one because the more specific method is hidden. Here is a somewhat artificial example:

interface Foo {
    void Bar(int a, int b = 1);
}

class FooImpl : Foo {
    public void Bar(int a, int b) {
        Console.WriteLine("bar/2");
    }
    public void Bar(int a) {
        Console.WriteLine("bar/1");
    }
}

If you do this

Foo f1 = new FooImpl();
f1.Bar(1); // Here, Bar(int a, int b = 1) is the only choice

bar/2 gets printed, but if you do this

FooImpl f2 = new FooImpl();
f2.Bar(1); // Here Bar(int a) of the implementation wins

bar/1 gets printed (demo).

like image 116
Sergey Kalinichenko Avatar answered Oct 09 '22 07:10

Sergey Kalinichenko


First lets understand what are optional parameter

The optional parameter, is just a syntax sugar in C#.

If you have the following method that uses optional parameter:

public void DeleteFiles(string extension = "*.*")

The real signature of this method is

public void DeleteFiles(string extension)

The compiler does the trick here, when you use this method like that:

obj.DeleteFiles();

When compiler was doing her job, he got call to DeleteFiles without parameters, and he try to find it, but he couldn't so he will try to find and overload that uses a optional parameter that can match, this time he found, the DeleteFile(string), and now he does the trick.

In fact the compiled code will be this:

var extension = "*.*";
obj.DeleteFiles(extension);

So if you try to do this code:

public class A
{
    public void DeleteFiles(string extension = "*.*")
    {
    }

    public void DeleteFiles(string extension2)
    {
    }
}

The compiler will give the following error message:

Error CS0111: Type 'A' already defines a member called 'DeleteFiles' with the same parameter types

Now lets your question

Now we have this class

public class A
{
    public void DeleteFiles(string folderPath)
    {
    }

    public void DeleteFiles(string folderPath, string extension = "*.*")
    {
    }
}

The real code in this case is

public class A
{
    public void DeleteFiles(string folderPath)
    {
    }

    public void DeleteFiles(string folderPath, string extension)
    {
    }
}

Then you have this code:

aInstance.DeleteFiles("path")

The compiler will look if there is a DeleteFiles method that receive one parameter. He will find it.

Conclusion

So in this case, the optional parameter feature, will never be used, because there is a perfect method signature that makes compiler never try to find a other signature that used optional parameter.

like image 22
Alberto Monteiro Avatar answered Oct 09 '22 09:10

Alberto Monteiro