In a previous post, we talked about the new "dynamic" keyword.
This next new features in C# 4.0 is one that I have been waiting on for years! And in the past it has always been explained away as an explicit design decision. Well, apparently pragmatism has won out and we now have default parameters in C#. In order to make default parameters even more useful, they threw in named parameters as a bonus! We will look at those in just a minute, but first, defaults.
Lets say we have a class like this:
public class TestClass { public void PerformOperation(string val1, int val2, double val3) { Console.WriteLine("{0},{1},{2}", val1, val2, val3); } }
Now we can instantiate and call this method on our class like this:
var testClass = new TestClass(); testClass.PerformOperation("val", 10, 12.2);
But what if we knew that the values we were already passing in were good defaults. Well, currently our option would be to create overloads and pass in defaults like this:
public class TestClass { public void PerformOperation() { PerformOperation("val", 10, 12.2); } public void PerformOperation(string val1) { PerformOperation(val1, 10, 12.2); } public void PerformOperation(string val1, int val2) { PerformOperation(val1, val2, 12.2); } public void PerformOperation(string val1, int val2, double val3) { Console.WriteLine("{0},{1},{2}", val1, val2, val3); } }
Pretty lengthy option. But C# 4.0 gives us an even better option in the form of parameter defaults.
public class TestClass { public void PerformOperation(string val1 = "val", int val2 = 10, double val3 = 12.2) { Console.WriteLine("{0},{1},{2}", val1, val2, val3); } }
How much cleaner is that? So, how would we call this? Just as you would with the overloads:
var testClass = new TestClass(); testClass.PerformOperation("val", 10);
Very nice. The third parameter in this call will be defaulted to 12.2, just like it was set that way. Now all of the VB.net developers can stop making fun of us. Now, you will also be happy to know that this works for constructors as well.
public class TestClass { public TestClass(string someValue = "testValue") { } public void PerformOperation(string val1 = "val", int val2 = 10, double val3 = 12.2) { Console.WriteLine("{0},{1},{2}", val1, val2, val3); } }
No more multiple constructor overloads to just specify a few default values.
So, what happens if we want to leave out "val2" in the call above? So, we want to fill in val1 (the first parameter) and we want to pass in val3 (the third parameters), but we want to default val2. We couldn’t call it like this:
var testClass = new TestClass(); testClass.PerformOperation("val", 10.2);
That wouldn’t compile since 10.2 cannot be converted to an int, since it is trying to default the third parameter here. So what option do we have? We can use named parameters. Named parameters simply consist of putting the parameter name, and then a colon in from of the value you are passing. So the call above would look like this:
var testClass = new TestClass(); testClass.PerformOperation("val", val3: 10.2);
Kinda neat, although I’m not sure how I feel about the fact that this will now make changing a parameter name a breaking change. I guess only time will tell how this plays out in large application development. Although I’m sure that people in other languages have been dealing with this for years.
Well, there you have it, yet another cool new feature of C# 4.0 and yet anther reason to look forward to VS2010.
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.
Because of Visual Basic.NET, changing parameter names was [i]already[/i] a breaking change, so this isn’t a new issue, it just actually impacts you now…
I’m also not entirely fond of the default value implementation, as (from what I’ve heard) it follows the VB.NET model where the parameter value is "baked into" the caller’s code, meaning you can’t change the default value and have it impact existing code (which is the supposed reason for the lack of default values in C# 1.0).
There is a way to do both, though: have the compiler automagically generate the overloads, e.g. if you write:
void Foo (int a = 1) {}
the compiler would generate:
void Foo () {Foo (1);}
void Foo (int a) {}
It’s "magical," but the compiler [i]already[/i] performs lots of "magic" with anonymous delegates, types, and lambdas, and this would have the added benefit that you could change the constant value and existing code would get the new value (as current overloading allows)…
But this isn’t apparently how they chose to implement it, probably because compiler-generated overloads don’t solve the named-parameter problem (which is useful for COM interop)…
So basically, C# is getting Optional Parameters; which VB has had for many years.
@Jonathan Excellent comments, as always. I’ll do a follow-up post which points out a few of these issues.
@Chris Yep, and Jonathan’s comments lay out why they avoided it for so long.
I think I have to agree with Jonathan and his implementation. I can’t say I’ll never use default parameters when/if they’re implemented but I like my current method of using overloaded methods.
That is a completely awesome addition to the C# language. I just wonder with the evolution of the language whether the entry point for new developers is being set to overwhelming levels. C# and .NET are rapidly expanding that it could be a victim of its own power. I love it though, haha. Good Job!
can a default value be set to a config appsetting?
This reminds me of VB4/5/6 with optional and default parameters. Although, I’m not sure that that makes it a bad thing. When I learned C# from a background in VB and discovered that the closest you could get was overloads and cascading invocations, I was disappointed. But I got over it. In like 5 minutes.
I wonder if the compiler is building overloads under the covers and if this is reflected in Reflector.
This is too good. Not too long ago, the c# purists were spitting upon this idea ( http://www.vbrad.com/article.aspx?id=65 ), e.g. it’s a hack, not oop enough, etc… Now, all of sudden, it’s cool. Enjoy the cool-aid.
I think in VB.NET you can do
Func(param1,,param2)
which doesn’t seem possibly in C# by this explanation.