views:

2254

answers:

8

I was watching Anders' talk about C# 4.0 and sneak preview of C# 5.0, and it got me thinking about when optional parameters are available in C# what is going to be the recommended way to declare methods that do not need all parameters specified?

For example something like the FileStream class has about fifteen different constructors which can be divided into logical 'families' e.g. the ones below from a string, the ones from an IntPtr and the ones from a 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 pattern could be simplified by having three constructors instead, and using optional parameters for the ones that can be defaulted, which would make the different families of constructors more distinct [note: I know this change will not be made in the BCL, I'm talking hypothetically for this type of situation].

What do you think? From C# 4.0 will it make more sense to make closely related groups of constructors and methods a single method with optional parameters, or is there a good reason to stick with the traditional many-overload mechanism?

+5  A: 

When a method overload normally performs the same thing with a different number of arguments then defaults will be used.

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

I used optional back in my VB6 days and have since missed it, it will reduce a lot of XML comment duplication in C#.

cfeduke
+1  A: 

I'm looking forward to optional parameters because it keeps what the defaults are closer to the method. So instead of dozens of lines for the overloads that just call the "expanded" method, you just define the method once and you can see what the optional parameters default to in the method signature. I'd rather look at:

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 really simple but the case in the OP with 5 overloads, things can get crowded real quick.

Mark A. Nicolosi
I've heard optional parameters should be last, shouldn't they?
Ilya Ryzhenkov
Depends on your design. Perhaps the 'start' argument is normally important, except when it's not. Perhaps you have the same signature somewhere else, meaning something different. For a contrived example,public Rectangle(int width, int height, Point innerSquareStart, Point innerSquareEnd) {}
Robert P
From what they said in the talk, optional parameters must be after required parameters.
Greg Beech
+1  A: 

I too am looking forward to optional parameters so I don't have to write XML docco for each overload!

Ty
+11  A: 

I'd consider the following:

  • Do you need your code to be used from languages which don't support optional parameters? If so, consider including the overloads.
  • Do you have any members on your team who violently oppose optional parameters? (Sometimes it's easier to live with a decision you don't like than to argue the case.)
  • Are you confident that your defaults won't change between builds of your code, or if they might, will your callers be okay with that?

I haven't checked how the defaults are going to work, but I'd assume that the default values will be baked into the calling code, much the same as references to const fields. That's usually okay - changes to a default value are pretty significant anyway - but those are the things to consider.

Jon Skeet
A: 

Just wait for c# 4.0, or create this method in vb.net and import the DLL to the c# project.

Why wait? The beta's been out for weeks.
John Saunders
Marked as "not helpful" because it doesn't answer the question, which is "in C# 4.0, how should optional args be used". Saying "just wait for C# 4.0" doesn't answer that question. Plus, creating a VB.NET assembly with optional arguments doesn't work: just because you can DECLARE a method with optional args in VB doesn't mean you can CALL that method from C#.
Seth Petry-Johnson
A: 

I will definitely be using the optional parameters feature of 4.0. It gets rid of the ridiculous ...

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 right where the caller can see them ...

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

Much more simple and much less error prone. I've actually seen this as a bug in the overload case ...

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

I have not played with the 4.0 complier yet, but I would not be shocked to learn that the complier simply emits the overloads for you.

JP Alioto
+2  A: 

i've been using Delphi, with optional parameters, forever. i've switched to using overloads instead.

Because when you go to create more overloads, you'll invariably confict with an optional parameter form; and you'll then have to convert them to non-optional anyway.

And i like the notion that there's generally one super method, and the rest are simpler wrappers around that one.

Ian Boyd
A: 

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

Optional arguments, when used in combination with named arguments, are extremely useful when combined with some long-argument-lists-with-all-optionals of COM calls.

Overloads are extremely useful when method is able to operate on many different argument types (just one of examples), and does castings internally, for instance; you just feed it with any data type that makes sense (that is accepted by some existing overload). Can't beat that with optional arguments.

mr.b