C# 7 Series, Part 3: Default Literals

C#’s default keyword has two kinds of usages: one is to label the fallback branch of the switch…case structure (for any path that does not fall into the case conditions); another is to represent the “default” value of a type. I will discuss this usage in this blog.

The default value of a type is either:

  • null, if the type is a reference type, or
  • an instance of the type constructed with the parameterless constructor, if the type is a value type.

The following screenshot is a quick example.

image

However, you can not have a default expression for any open type (Note: An open type is a type that has unbound type arguments; a type has all bound type arguments is called closed type), for example:

image

Now, if we want to use default value for a generic type in a method, we have to write code like this:

 public static void Method(ImmutableArray<int> array) { }
 
public static void Main(string[] args)
{     
    Method(default(ImmutableArray<int>));
}

Do you see a redundant here? the compiler should know the exact type needed for the Method() for the first parameter. A default literal without the type specification should be sufficient enough.

Default Literals

C# 7.1 allows the default expressions. If compile with the C# language version 7.1, or latest, you can simplify the code as the following:

 public static void Method(ImmutableArray<int> array) { }
public static void Main(string[] args)
{ 
    Method(default);
}

Now you get a clean code!

Similarly, you can have default literals for all the place that default(…) can appear:

 public static void Main(string[] args = default)    // Default value for the optional parameter        {
    int i = default;        // Default value (0) for type System.Int32 
    string s = default;     // Default value (null) for type System.String 
    Method(default);        // Calling a method with default value for an argument 
    T t = default;          // Default value for a type parameter 
    return default;         // Default return value for a method that does not return void 
}

You can have default literals in a condition test:

 int x = 2; 
if (x == default) { }       // Test if x is default value (0) of the type System.Int32 
if (x is default) { }       // Same as above

More interestingly, you can use default literals in switch…case. Oh, cool! but… wait, how about the label ‘case default’? Here is what I get from the IDE:

image

And if you apply the fix, it will be:

 int x = 2; 
switch (x) 
{ 
    case (default): break; 
    default: break; 
}

This looks confusing, but at least we get live analytics about this, Thanks Roslyn!

The last thing I want to call out is there are cases that cannot apply default literals, for example:

 // Error: 'as' must have reference type 
default as int; 
// OK. But the left hand expression is always null.
if (default as string == string.Empty) { }
// Error. Cannot apply operator 'is' to type 'default'.
if (default is string) { }

Conclusion

Default literals in C# 7.1 avoids redundant typing where the default value is known to compiler. This is a syntactical improvement and nothing changed for the CLR, The new code is 100% compatible with the code built by earlier versions of the C# compiler.