Should you declare methods using overloads or optional parameters in C # 4.0?

I watched Anders' Story about C # 4.0 and a preview of C # 5.0 , and I wondered when additional C # parameters were available, what would be the recommended way to declare methods that don't need all of the specified parameters?

For example, something like the FileStream class has about fifteen different constructors that can be divided into logical “families”, for example. those listed below are from the IntPtr line and those from SafeFileHandle .

 FileStream(string,FileMode); FileStream(string,FileMode,FileAccess); FileStream(string,FileMode,FileAccess,FileShare); FileStream(string,FileMode,FileAccess,FileShare,int); FileStream(string,FileMode,FileAccess,FileShare,int,bool); 

It seems to me that this type of template can be simplified by using three constructors and using optional parameters for those that may be defaulted, which would make the different families of constructors more clear [note: I know this change will not be made in BCL, I'm hypothetically talking about this type of situation].

What do you think? From C # 4.0, would it be more appropriate to create closely related groups of constructors and methods with a single method with optional parameters, or is there a good reason to stick to the traditional multi-load mechanism?

+81
c # overloading optional-parameters
Oct 30 '08 at 21:42
source share
12 answers

I would consider the following:

  • Do you need your code for use with languages ​​that do not support additional parameters? If so, consider enabling overloads.
  • Do you have members of your team who vehemently oppose optional parameters? (Sometimes it’s easier to live with a decision that you don’t like than to argue this case.)
  • Are you sure that your default values ​​will not change between the lines of your code, or if they can, your subscribers will be fine with this?

I did not check how the defaults would work, but I would assume that the default values ​​would be baked in the calling code, much like the const field references. This is usually normal - the default changes are significant in any case, but this is something to consider.

+103
Oct 30 '08 at 21:55
source share

If method overloading usually does the same thing with a different number of arguments, then the default values ​​will be used.

If method overloading performs a function differently based on its parameters, then overloading will continue to be used.

I used optionally in my days VB6 and since then skipped it, this will reduce a lot of duplication of XML comments in C #.

+16
Oct 30 '08 at 21:47
source share

I used Delphi with optional parameters forever. Instead, I switched to using overloads.

Because when you move on to creating more overloads, you will certainly come across an optional parameter form; and then you have to convert them to an optional option.

And I like the notion that there is usually one super method, and the rest are simpler wrappers around this.

+10
Jun 24 '09 at 16:55
source share

I will definitely use the advanced parameters feature 4.0. He gets rid of the funny ...

 public void M1( string foo, string bar ) { // do that thang } public void M1( string foo ) { M1( foo, "bar default" ); // I have always hated this line of code specifically } 

... and puts the values ​​to the right, where the caller can see them ...

 public void M1( string foo, string bar = "bar default" ) { // do that thang } 

Much easier and much less error prone. I really saw this as an error in case of overload ...

 public void M1( string foo ) { M2( foo, "bar default" ); // oops! I meant M1! } 

I have not played with the 4.0 compiler yet, but I would not be shocked to find out that complier just emits overloads for you.

+6
Jun 24 '09 at 16:53
source share

Optional parameters are essentially the metadata part that the compiler directs to the method call to insert the appropriate default values ​​on the call site. In contrast, overloads provide a means by which the compiler can select one of several methods, some of which can themselves give default values. Note: if someone tries to call a method that specifies optional parameters from code written in a language that does not support them, the compiler will require you to specify "optional" parameters, but since calling a method without specifying an optional parameter is equivalent to calling it with a parameter equal to to the default value, there are no barriers to such languages ​​invoking such methods.

A significant consequence of linking optional parameters on the call site is that they will be assigned values ​​based on the version of the target code available to the compiler. If the Foo assembly has a Boo(int) method with a default value of 5, and the Bar assembly contains a call to Foo.Boo() , the compiler will treat this as Foo.Boo(5) . If the default value is changed to 6 and the Foo assembly is recompiled, Bar will continue to call Foo.Boo(5) if before or after recompiling with this new version of Foo . Therefore, you should avoid using optional parameters for things that may change.

+5
Jan 21 '13 at 1:41
source share

I look forward to additional parameters, because it saves what is closer to the method by default. Therefore, instead of dozens of lines for overloads, which are simply called the “advanced” method, you simply define the method once, and you can see what default parameters are set in the method signature. I would rather see:

 public Rectangle (Point start = Point.Zero, int width, int height) { Start = start; Width = width; Height = height; } 

Instead of this:

 public Rectangle (Point start, int width, int height) { Start = start; Width = width; Height = height; } public Rectangle (int width, int height) : this (Point.Zero, width, height) { } 

Obviously this example is very simple, but the case is in OP with 5 overloads, things can quickly overflow.

+3
30 Oct. '08 at 21:51
source share

It can be argued whether optional arguments or overloads should be used, but most importantly, everyone has their own area where they are irreplaceable.

Additional arguments when used in conjunction with named arguments are extremely useful in combination with some long list arguments with all possible COM calls.

Overloads are extremely useful when a method is able to work with many different types of arguments (just one example) and, for example, performs casting; you just load it with any data type that makes sense (which is accepted by some existing overload). It is not possible to beat this with additional arguments.

+2
May 21 '10 at 10:16
source share

One of my favorites regarding additional parameters is that you see what happens to your parameters if you do not provide them without going to the definition of the method. Visual Studio will simply show you the default value for the parameter when entering the method name. Using the overload method, you are stuck on reading (even if available) the documentation or directly going to the definition of the methods (if it exists) and to which method the overload is overloaded.

In particular: proposal documents can quickly increase by the number of overloads, and you will probably end up copying existing comments from existing overloads. This is quite annoying as it does not bring any value and violates the DRY principle ). On the other hand, with an optional parameter, there is exactly one place where all parameters are documented, and you see their value, as well as their default values when typing.

And last but not least, if you are a consumer of the API, you can not look at the implementation details (because you don’t have the source code), and therefore they don’t have the opportunity to see which super-method is overloaded wrapped. Thus, you are stuck reading a document and hope that all the default values ​​are listed there, but this is not always the case.

Of course, this is not an answer that handles all aspects, but I think it adds one that is not yet considered.

+2
Mar 08 '16 at 8:12
source share

Both parameters, method overloading, have their advantages or disadvantages. It depends on your preference to choose between them.

Optional parameter: only available in .Net 4.0. an optional parameter reduces the size of your code. You cannot define and edit a parameter

overloaded methods: you can define and edit parameters. The code size will increase, but the overloaded method is easy to understand.

0
Dec 31 '13 at 7:27
source share

While they (presumably?) Are two conceptually equivalent ways that you can model your API from scratch, they unfortunately have a slight difference when you need to consider backward compatibility over time for old clients in the wild. My colleague (thanks Brent!) Pointed me to this one . Some quotes from this:

The reason that additional parameters were introduced in C # 4 in the first place is support for COM interoperability. This is it. And now, they were learning about the consequences of this fact. If you have a method with additional parameters, you can never add overload using additional optional parameters for fear of causing compile time breakage change. And you can never remove an existing overload, since that was always a change in runtime. You pretty much need to consider it as an interface. Your only recourse in this case is to write a new method with a new name. Therefore, keep this in mind if you plan to use optional arguments in your APIs.

0
Sep 14 '16 at 19:58
source share

To add futility when using overload instead of options:

Whenever you have a number of parameters that only make sense together, do not enter optional options into them.

Or, in general, whenever your method signatures allow you to use usage patterns that don't make sense, limit the number of permutations of possible calls. For example, using overloads instead of optional ones (this rule is also true if you have several parameters of the same data type, by the way, devices such as factory methods or custom data types can help here).

Example:

 enum Match { Regex, Wildcard, ContainsString, } // Don't: This way, Enumerate() can be called in a way // which does not make sense: IEnumerable<string> Enumerate(string searchPattern = null, Match match = Match.Regex, SearchOption searchOption = SearchOption.TopDirectoryOnly); // Better: Provide only overloads which cannot be mis-used: IEnumerable<string> Enumerate(SearchOption searchOption = SearchOption.TopDirectoryOnly); IEnumerable<string> Enumerate(string searchPattern, Match match, SearchOption searchOption = SearchOption.TopDirectoryOnly); 
0
Dec 08 '17 at 13:52
source share

In many cases, optional parameters are used to switch performance. For example:

 decimal GetPrice(string productName, decimal discountPercentage = 0) { decimal basePrice = CalculateBasePrice(productName); if (discountPercentage > 0) return basePrice * (1 - discountPercentage / 100); else return basePrice; } 

The discount parameter here is used to feed the if-then-else statement. There is a polymorphism that was not recognized, and then it was implemented as an if-then-else statement. In such cases, it is much better to separate the two control flows into two independent methods:

 decimal GetPrice(string productName) { decimal basePrice = CalculateBasePrice(productName); return basePrice; } decimal GetPrice(string productName, decimal discountPercentage) { if (discountPercentage <= 0) throw new ArgumentException(); decimal basePrice = GetPrice(productName); decimal discountedPrice = basePrice * (1 - discountPercentage / 100); return discountedPrice; } 

Thus, we even protected the class from receiving a call with a zero discount. This call will mean that the caller believes that there is a discount, but in fact the discount does not exist at all. Such a misunderstanding can easily cause an error.

In such cases, I prefer not to have optional parameters, but in order to force the caller to explicitly select the execution script that matches his current situation.

The situation is very similar to parameters, which can be null. The same is a bad idea when an implementation boils down to statements like if (x == null) .

You will find a detailed analysis of these links Avoid Additional Parameters and Avoid Zero Parameters

-one
Jun 10 '15 at 8:58
source share



All Articles