Back to Blog
C#

C# Default Keyword: Syntax and Use Cases

Learn how the C# default keyword works for value types, reference types, generics, and the default literal in modern C#.

C#default keywordgeneric typesdefault literalC# syntax
C# code editor showing default keyword usage with type inference

In C#, the default keyword has two related forms: the default(T) expression and the default literal. Both provide a way to obtain the default value of a type, but they serve different syntactic roles. Misunderstanding these forms can lead to compile-time errors or subtle runtime bugs, especially in generic code.

The Default Operator for Value Types

For a value type, default(T) returns an instance where every field is set to its default value. For numeric types, that is zero; for bool, it is false; for char, it is \0; for enums, it is zero even if zero is not a defined enum member.

int number = default(int); // 0 bool flag = default(bool); // false char letter = default(char); // '\0' DayOfWeek day = default(DayOfWeek); // (DayOfWeek)0, which is Sunday

The expression default(int) is a compile-time constant, so it can be used in contexts that require constants, such as attribute arguments or switch case labels, although you would rarely need to do so.

Default Values for Reference Types

For reference types, default(T) returns null. This applies to classes, interfaces, delegates, arrays, and string.

string text = default(string); // null Stream stream = default(Stream); // null Action callback = default(Action); // null

This seems straightforward, but it becomes important when you have a variable that may or may not be assigned. Using default explicitly communicates intent compared to simply initializing with null.

The Default Literal in Modern C#

C# 7.1 introduced the default literal, which lets you omit the type when the compiler can infer it. The target type must be known at compile time.

int number = default; // equivalent to default(int) string text = default; // equivalent to default(string) MyClass obj = default; // null

The literal is especially useful with generics, where you want a fallback value without knowing the exact type.

Using Default with Generic Types

In a generic method or class, you often need to return a neutral value. The default keyword handles both value and reference types correctly.

public T GetDefault<T>() { return default(T); }

With the default literal, you can simplify this:

public T GetDefault<T>() { return default; }

The literal works whenever the target type is known, so T is sufficient here. With Nullable<T>, default returns a Nullable<T> instance with HasValue == false. It is not a null reference, but a comparison such as value == null returns true because Nullable<T> defines lifted operators.

Pitfalls and Common Mistakes

A common mistake is to think that default(int?) is null in the same way as a reference type. It is actually a Nullable<int> value with HasValue == false. Equality comparisons against null work because Nullable<T> provides lifted operators, not because the value is a null reference.

Another common error is using default where no target type is available, such as in a var declaration:

var result = default; // error: no target type for the default literal

This fails because var does not provide a target type. You must specify the type.

Default in Conditional Expressions and Switch Statements

The default literal can appear in a conditional expression when the expression has a target type. For example:

object obj = condition ? "text" : default;

Here the target type is object, so default means default(object) and evaluates to null.

In a switch statement, default: is the label for unmatched cases. In a switch expression, use the _ discard pattern instead:

string Describe(object value) => value switch { int i => $"Integer: {i}", string s => $"String: {s}", _ => "Unknown" };

Performance

The default keyword is a compile-time construct. For value types, default(T) produces the same result as initializing each field of a struct to its default value. For reference types, it produces null. There is no meaningful runtime overhead compared with writing 0 or null explicitly.

Compatibility and Language Version Notes

The default literal requires C# 7.1 or later. If your project uses an older language version, use default(T) instead. The behavior of default(T) for a given type is stable across C# versions; the literal is only syntactic shorthand.

When source generators or analyzers emit generated code, they may use the default literal. That is valid as long as the project's language version supports C# 7.1 or later.

C# Default Keyword: Practical Usage and Code Examples | RYUSLOG DEV