Friday, April 15, 2011

C# .Net 4.0 Named and Default Parameters

What value do you think named and default parameters will add in C#.Net 4.0?

What would be a good use for these (that hasn't already been achieved with overloading and overriding)?

From stackoverflow
  • It will make COM interop a lot easier.

    Until C# 4 VB.Net was a much better language for interop. Without defaults you have massive lists of dummy ref parameters in C#.

    Kibbee : Is that really a good thing :)
    Keith : Yes - until the big MS bite the bullet and produce a real managed OS (which I can't see them doing any time soon) some apps are going to have to deal with unmanaged calls.
  • Brevity of code is the obvious one that springs to mind. Why define several overloads when you can define one function. Also, though, if you have two identically typed parameters, it isn't always possible to construct the full set of overloads you might need.

  • It can make constructors simpler, especially for immutable types (which are important for threading) - see here for a full discussion. Not as nice as it should be perhaps, but nicer than having lots of overloads. You obviously can't use object initializers with immutable objects, so the usual:

    new Foo {Id = 25, Name = "Fred"}

    isn't available; I'll settle for:

    new Foo (Id: 25, Name: "Fred")

    This can be extended to the general idea of simplifying overloads, but in most cases I'd prefer overloads that advertise the legal combinations. Constructors are a bit different, IMO, since you are just (typically) defining the initial state.

    The COM side of things is also important to a lot of people, but I simply don't use much COM interop - so this isn't as important to me.

    Edit re comments; why didn't they just use the same syntax that attributes use? Simple - it can be ambiguous with other members / variables (which isn't an issue with attributes); take the example:

    [XmlElement("foo", Namespace = "bar")]

    which uses one regular parameter (to the ctor, "foo"), and one named assignment. So suppose we use this for regular named arguments:

    SomeMethod("foo", SecondArg = "bar");

    (which could also be a constructor; I've used a method for simplicity)

    Now... what if we have a variable or a property called SecondArg? This would be ambiguous between using SecondArg as a named argument to SomeMethod, and assigning "bar" to SecondArg, and passing "bar" as a regular argument.

    To illustrate, this is legal in C# 3.0:

        static void SomeMethod(string x, string y) { }
        static void Main()
            string SecondArg;
            SomeMethod("foo", SecondArg = "bar");

    Obviously, SecondArg could be a property, field, varialble, etc...

    The alternative syntax doesn't have this ambiguity.

    Edit - this section by 280Z28: Sorry for adding this here, but it's not really a unique answer and it's too long for the comments and includes code. You hinted at the ambiguity but your example didn't highlight the deciding case. I think the example you gave points out something that could be confusing, but the required {} around object initializers prevents an underlying syntactical ambiguity. My explanation for the following code is embedded as the multi-line block comment.

    public sealed class SomeAttribute : Attribute
        public SomeAttribute() { }
        public SomeAttribute(int SomeVariable)
            this.SomeVariable = SomeVariable;
        public int SomeVariable
    /* Here's the true ambiguity: When you add an attribute, and only in this case
     * there would be no way without a new syntax to use named arguments with attributes.
     * This is a particular problem because attributes are a prime candidate for
     * constructor simplification for immutable data types.
    // This calls the constructor with 1 arg
    [Some(SomeVariable: 3)]
    // This calls the constructor with 0 args, followed by setting a property
    [Some(SomeVariable = 3)]
    public class SomeClass

    Daniel Earwicker : Ooh, very nice. I was thinking they'd have to allow readonlys to be assigned to from initializer blocks, but that idea gets messy very quickly. This is much better.
    Daniel Earwicker : Although as you say, it would be nice if the constructor appeared by magic.
    280Z28 : I'm curious why they didn't borrow the named arguments syntax used by attributes.
    Marc Gravell : @280Z28 - I'll illustrate by an update...
    280Z28 : @Marc: I posted my reply at the bottom of your answer. :)
  • It will help to dodge the problem of providing a decent API to work with Office applications! :)

    Some parts of the Office API are okay, but there are edge cases that were clearly designed for use from a language with optional/named parameters. So that's why C# has to have them.

    Keith : That's kinda what I said ;) When working with the Office API VB.Net is miles easier to work with than C#
  • Optional parameters also avoid the problem where classes provide dozens of methods that are just variations on the arguments accepted.

    Consider the Exception class. Instead of one constructor with optional arguments, it has four constructors for each combination of 'has message', and 'has inner exception'. That's alright, but now consider what happens if you provide a null value to a constructor taking an innerException? Does it act exactly like the constructor with with no innerException parameter, sortof like the constructor with no innerException parameter, or does it throw a null reference exception?

    A single constructor with 2 optional parameters would have made it more obvious that passing a null innerException was equivalent to not including it at all. A perfect place for default arguments.

    Also don't forget that now every derived Exception class also has to include 4 constructors, which is a pointless hassle.


Post a Comment