This post was migrated from Justin’s personal blog, 'Codethinked.com.' Views, opinions, and colorful expressions should be taken in context, and do not necessarily represent those of Simple Thread (and were written under the influence of dangerous levels of caffeination).

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.

10 Comments

Jonathan Pryor

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)…

Reply
Justin Etheredge

@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.

Reply
Jeff Sheldon

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.

Reply
Khalid Abuhakmeh

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!

Reply
Jon Davis

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.

Reply
Chase Saunders

I think in VB.NET you can do

Func(param1,,param2)

which doesn’t seem possibly in C# by this explanation.

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *