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