Click here to Skip to main content
15,884,472 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hello,

This may not be the most common question, but it's bugging me.

Lets say, I have a method that is overloaded a couple times to have all logic in one place like this(dumb example, but it kind covers what I'm saying):

C#
public int sum(int x, int y) 
{
   return sum(x,y,0,0,0);
}

public int sum(int x, int y, int w) 
{
    return sum(x,y,w,0,o);
}

public int sum(int x, int y, int w, int z) 
{
    return sum(x,y,w,z,0);
}

public int sum(int x, int y, int w, int z, int a) 
{
    int result = x+y+w+z+a;
    return result;
}


and the option to make a single method with optional fields

C#
public int (int x, int y, int w = 0, int z = 0, int a = 0)
{
    int result = x+y+w+z+a;
    return result;
}


All explained, here are the questions. Do they become the same in terms of performance and overhead? Please, can anyone tell me if it will end up the same on the IL and I'm talking crazy stuff :P ?
The plan is to implement this on a good size project, so if someone has some experience on both uses(good and bad), I would appreciate to hear from.

Regards
Posted
Comments
Sascha Lefèvre 13-Apr-15 13:36pm    
Not exactly an answer to your questions: If there is a difference in performance it will be negligible. But you will eventually bless the day when you decided to go for the overload-approach because it will be so much easier to maintain; especially in a "good size project".
Sergey Alexandrovich Kryukov 13-Apr-15 13:47pm    
Please, I don't see how "overloading" can be any better for support? Could you explain in on examples where one alternative is better? Please see my answer for explanation of my reasons.
—SA
Sascha Lefèvre 13-Apr-15 15:25pm    
Please see my reply comment to Paulo below. /Sascha
Paulo Augusto Kunzel 13-Apr-15 14:10pm    
Hi Sascha,
please, could you provide an example or elaborate your comment?
It is not that I"m doubting you, but the way I see it maintainability looks easier using optional parametrs. But I might be wrong and that is what I'm trying to find out.
Sascha Lefèvre 13-Apr-15 15:23pm    
Hi Paulo!
Richard already pointed out my main arguments for overloads. While it's certainly possible to circumvent all potential pitfalls of default parameters, I would argue why take the risk if you don't have to?
If you have that many overloads that code readability really becomes an issue, you have two options to remedy that: If you are "a fan of regions", hide them in a region. If you aren't, stow the "proxy"-overloads away in a partial class file.
And one additional benefit of overloads: If you let Visual Studio "Find All References" it will show you exactly the references of the "selected" overload. When using optional parameters, it will show you all references; but you might be interested in just one particular "parameter-use" and would have to scan through the whole "Find Symbol Results"-List.
/Sascha

They certainly won't produce the same IL - the overloads version will generate four methods, and the optional parameters version will only generate one.

With the overloads version, it's easier to change the default value of a parameter. With optional parameters, the default value is "baked in" to the caller, so you would have to recompile everything for the new default to take effect.

If you're not careful, optional parameters can introduce versioning problems, as Phil Haack described in 2010:
Versioning Issues With Optional Arguments[^]
More Versioning Fun With Optional Arguments[^]

Interfaces and sub-classes can make life interesting as well:
C# Fundamentals: Optional Parameters - Pros and Pitfalls[^]
C#
public interface ITag 
{
   void WriteTag(string tagName = "ITag");
} 

public class BaseTag : ITag 
{
   public virtual void WriteTag(string tagName = "BaseTag") 
   { 
      Console.WriteLine(tagName); 
   }
} 

public class SubTag : BaseTag 
{
   public override void WriteTag(string tagName = "SubTag") 
   { 
      Console.WriteLine(tagName); 
   }
} 

public static class Program 
{
   public static void Main() 
   {
      SubTag subTag = new SubTag();
      BaseTag subByBaseTag = subTag;
      ITag subByInterfaceTag = subTag; 

      subTag.WriteTag();             // Output: SubTag
      subByBaseTag.WriteTag();       // Output: BaseTag
      subByInterfaceTag.WriteTag();  // Output: ITag
   }
}
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 13-Apr-15 13:50pm    
Good points and explanation, a 5.
But I would be curious: don't you see some obvious benefits of optional parameters? You never suggested any preferences...
—SA
Richard Deeming 13-Apr-15 14:11pm    
I can certainly see the benefits, and I've used optional parameters to greatly simplify some of my own code. You just have to be careful, particularly with the versioning issues. :)
Sergey Alexandrovich Kryukov 13-Apr-15 14:27pm    
Very good. Having all that in mind, I still recommend the inquirer to consider using optional parameters. The biggest possible concern I had would be the need to down-grade code to older C# versions not supporting the feature, but the inquirer stated it won't be a concern; please see the discussion of Solution 3.
—SA
In this case I would vote for optional parameters because what you are doing seems "orthogonal" to me: there's no significant variation.

You could also consider using Enumerable.Sum:
C#
// requires Linq and .NET 3.5
public int SumAll(params int[] values)
{
    return values.Sum();
}
The 'Sum overloads of Enumerable allow you to use a wide variety of Types and optional Func for transformation, or whatever: [^].

You could even use Array.ForEach (.NET 3.0).

I suspect that all of these implementations would perform equally well given the simplicity of what you are doing, and the current sophistication of the .NET compiler's optimizations.

And, in the long run, I think that making your code self-documenting ... expressing your intent in the structure of the code so it is is clear, over times, to others ... can be just as important a factor in the syntax you use to implement this method.
 
Share this answer
 
Comments
Paulo Augusto Kunzel 13-Apr-15 13:53pm    
Hi Bill,

you suggestion turns the example into a better implementation. But that was simply an example, I was looking more in the lines comparing the overloading of methods against the optional parameters on a program that has (on a very simplified level) the same logic as the example.

You are probably right, in the long if it is readable and well documented it should be fine. But it never hurts to ask just to be on the safe side. :)

thank you
BillWoodruff 13-Apr-15 14:22pm    
Hi Paulo, I'm not sure that anything I suggested is a "better" implementation :)

In this case, given my belief that performance differences would be small, I would choose the syntax/format that I felt best contributed to the clarity and expressiveness of the code over time. And, that choice would be influenced by the "context" of the code: it's purpose; whether it's for myself, or others, it's possible future modifications/maintenance, etc.

Perhaps you've heard of the software-development "principles" of "least surprise," and "least astonishment" ? Well, who is surprised, or astonished, depends on who is looking at the code ... yes :) ?

cheers, Bill
Historically, option parameters weren't introduced. In later versions of C#, this feature have been added. That said, optional parameters have additional value for developers. I think this value is quite obvious: you have less methods; the whole thing is somewhat easier for maintenance; you have less code; the code is more readable overall.

You are the one who has to decide on that. Say, if there is a chance of down-grading the code to older versions of C#, using "overloading" is safer, won't require modification of code back to "overloading". In all other cases, I would prefer optional parameters. But you decide.

[EDIT]

I discussed performance considerations in detail, in the comments to this answers, below.

—SA
 
Share this answer
 
v2
Comments
Paulo Augusto Kunzel 13-Apr-15 14:07pm    
Hi Sergey,

I totally agree with you on both easier maintenance and me being the one to decide. It is quite unlikely (to avoid using never) that we will come into the need of down-grading the code to older versions.
To be honest, I'm thinking about using the optional parameters. But before that, I believe it is common sense to get input from people outside my normal circle of developers. There is always a chance someone will see something we missed.

Thank you for taking the time to answer my question.

Regards
Sergey Alexandrovich Kryukov 13-Apr-15 14:24pm    
All right, I explained the benefits of those optional parameters, didn't I?
If you have any concerns, doubts against them, feel free to ask some follow-up questions. If it seems clear to your, will you accept this answer formally (as well as some other answers)?
—SA
Paulo Augusto Kunzel 13-Apr-15 14:54pm    
Sergey,
You certainly did, no doubt about that. There was just a couple things I would like to from my original question I want to check with you. And yes, I'll accept the answer formally, that is the very least I can do for people who take the time to answer (correctly :P ).

Are you aware of any performance or overhead issue that can come from using optional parameters? Do you know the they look similar in the I.L. (just wondering)

thanks in advance
Sergey Alexandrovich Kryukov 13-Apr-15 15:03pm    
Ah, performance... Right. There should not be considerable (or even easily noticeable) performance difference, but performance of optional parameters, theoretically cannot be any worse, it can only be better.

I'll explain: it can do exactly the same as with "overloading", but "overloading" has some overhead: it makes on extra method call. Let's see: to re-use all those methods, you need to implement one method with full list of arguments, and then call it from each of the methods with shortened list of arguments. This is that extra call. If you neglect re-use, you will have to repeat identical code, which would make the whole thing non-maintainable; and the overhead would be in the volume of the code, due to redundancy.

This way, even in this aspect, optional parameters are still preferable.

By the way, if you want to experiment with performance, always use the class System.Diagnostics.StopWatch (it gives you the best accuracy, very high on nearly all systems). But 1) don't forget to exclude JIT-compilation from timing (this is the most important factor), 2) collect a lot of statistic: performance is a VERY random thing, the statistical dispersion of timing result may be just great, due to many random factors.

You still didn't accept any answers; there is such an "Accept" button...

—SA
Paulo Augusto Kunzel 13-Apr-15 15:18pm    
Nice. this is exactly the type of thing I need.

I know, I got caught up on something else and forgot that the button doesn't push itself.. lol.. But I would have looked it know regardless.

Thank you
In practice, you just have to use some common senses and answer some simple questions like:

Do you want the implementation method to be public?
In some cases, it does not make sense to have all parameters at once as some of them might be exclusive.

Does the function with less parameters should call the one with more or vice versa? In the above case, it would make more sense to reverse the direction like this (only one case shown):

C#
public int sum(int x, int y, int w)
{
  return sum(x, y) + w;
}


Another fact is that when parameters are of different data types, there might not be a single order that make sense (and you don't necessarily want to use named parameters).

As proposes in one solution, the params alternative can make a lot of sense if you have more that a given number of parameters. For a case like an addition, you might provide optimized version for 2 or 3 parameters and the general one above that.

In practice, you also consider the amount of code. In an example like the one above where it take more code to call the other version and the code is trivial, I might simply write the whole addition in each overload particulary if the function are used a lot.

Also, default values are not always simple constants so overload might sometime make sense because you might get the value using some code. And in cases like a virtual function, I would generally avoid default parameters and only have the implementation function virtual.

Another point would be the validation you might do on parameters or the usefullness of finding specific references or add a breakpoint only in a specific case.

Thus except for some trivial cases where it does not matter much, common sense should tell the more appropriate solution.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900