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.
Comments
- Anonymous
June 06, 2017
How do you differentiate between 'case default' and 'default' in goto statements? Would it be 'goto (default)' vs 'goto default'?- Anonymous
June 06, 2017
Ah it would be 'goto case default', doh! Sorry Mark. - Anonymous
June 12, 2017
If you need use "goto" statement in your code that means something goes terribly wrong- Anonymous
June 16, 2017
I would say it really depend on what problem needs to solve by "goto". There are cases such as switch-case that use 'fall through' requires "goto", e.g.switch (i){case 0: // direct fall-through without using "goto", as no body inside this "case".case 1: // something done here goto case 2; // we need "goto" here as there IS body.case 2: // do things break;default: break;}Of course you are saying other kinds of "goto" (from traditional C/C++ thought), unfortunately, I also saw some code from .NET Core that really requires this kind of goto in order to write less similar-to-same code.
- Anonymous
- Anonymous
- Anonymous
June 06, 2017
What if you have multiple parameters in a method? In my opinion the default keyword is much less readable than having the type as parameter. For example:Method(default(ImmutableArray), default(ImmutableArray), default(ImmutableArray));vsMethod(default, default, default); // hard to remember which one is which?- Anonymous
June 12, 2017
In my opinion if you want to allow for this kind situation is better to introduce optional parameters:Method(ImmutableArray a = default, ImmutableArray b = default, ImmutableArray c = default) - Anonymous
June 13, 2017
This is true for any literal. I am working on a c# 7.2 feature to address this: an improvement to named arguments. You will be able to writeM(ignoreEmpty: true, accumulator, cancellation: default);
.It is more informative to specify the name of the argument, than the type indefault
.
- Anonymous
- Anonymous
June 12, 2017
why not a three letter word like "def" instead of "default" .. you don't use def anywhere in c# seriously "default" will creap in the code.. =) , even just underscore "_" would have been better than both.. return _ ;string[] args = _ ;- Anonymous
June 14, 2017
Many people, me included, will always choose readability over length of the code. There's no way I could choose cryptic special characters over plain English words.
- Anonymous
- Anonymous
January 25, 2019
The default literal is never constructed with the parameterless constructor.Most value types don't have a parameterless constructor.If you happen to find one, it is invoked only with a 'new' expression. - Anonymous
May 22, 2019
when redundant vs readable/maintainable, which one do you choose?