Back to Blog
C#

C# Nullable GetValueOrDefault: Usage and Behavior

Understand C# Nullable<T>.GetValueOrDefault: its overloads, behavior with HasValue, comparison with ??, and usage in LINQ and production code.

C#Nullable.NETGetValueOrDefault
Diagram showing a nullable value being resolved to either its underlying value or a default fallback using GetValueOrDefault.

In C#, Nullable<T> (often written as T? for value types) represents a value type that may be undefined. GetValueOrDefault() safely reads the underlying value: it returns the value when HasValue is true and otherwise returns the default value of T or a supplied fallback. The examples below cover both overloads, their behavior, comparisons with ??, and common usage in production code and LINQ.

The Two Overloads of GetValueOrDefault

Nullable<T> exposes two overloads:

  • GetValueOrDefault() returns the underlying value if HasValue is true; otherwise it returns default(T).
  • GetValueOrDefault(T defaultValue) returns the underlying value if HasValue is true; otherwise it returns the supplied defaultValue.
int? maybeNumber = null; int result1 = maybeNumber.GetValueOrDefault(); // 0 int result2 = maybeNumber.GetValueOrDefault(42); // 42 maybeNumber = 7; int result3 = maybeNumber.GetValueOrDefault(); // 7 int result4 = maybeNumber.GetValueOrDefault(42); // 7

The parameterless overload is useful when the natural default value of the type is appropriate. The overload with a parameter lets you specify a fallback that is meaningful for your domain.

How GetValueOrDefault Handles HasValue

The method checks the HasValue property internally. If HasValue is true, it returns the stored value. If false, it returns the default value. This is equivalent to writing:

int? maybe = null; int result = maybe.HasValue ? maybe.Value : 0;

GetValueOrDefault is more concise and avoids the risk of accessing .Value when HasValue is false, which would throw an InvalidOperationException. The method never throws, so it is safe to call on a Nullable<T> instance whose HasValue is false.

GetValueOrDefault vs the Null-Coalescing Operator

The null-coalescing operator (??) is a common alternative:

int? maybe = null; int result = maybe ?? 0;

Both approaches return the same result for value types. The difference is subtle: ?? works with any nullable type, including reference types and Nullable<T>, while GetValueOrDefault is specific to Nullable<T>. For value types, they are functionally equivalent.

One benefit of GetValueOrDefault is that it is a named method and can be used in a method group, which ?? cannot:

Func<int> getDefault = maybeNumber.GetValueOrDefault;

In most straightforward scenarios, the choice is a matter of readability. The ?? operator is often more idiomatic, but GetValueOrDefault communicates the intent of "give me the value or a default" more explicitly.

Common Mistakes and Edge Cases

One common mistake is assuming GetValueOrDefault works on nullable reference types. It is only defined for Nullable<T>, whose type parameter is constrained to a struct. For nullable reference types, use ?? or the null-conditional operator.

Another edge case is when T is itself a nullable type. For example, int?? is not valid C#; Nullable<T> cannot be nested. So you cannot have a nullable of a nullable.

Also note that for value types, default(T) is the zero-initialized value: 0 for numeric types, false for bool, and the zeroed state for other structs. If you need a non-default fallback, use the overload with an explicit default.

Performance and Runtime Behavior

GetValueOrDefault is a simple method that checks a boolean field and returns either a stored value or a default. It does not allocate heap memory, throw exceptions, or perform boxing. The JIT can often inline it, so the runtime cost is negligible. In performance-sensitive code, you can use it freely without worrying about overhead. The method returns a copy of the value, which is expected for value types.

When to Prefer GetValueOrDefault in Production Code

Use GetValueOrDefault when you need to retrieve a value from a nullable and you have a sensible default that is not the natural default for the type. For example, when reading a configuration value that might be absent:

int? timeout = GetTimeoutFromConfig(); int effectiveTimeout = timeout.GetValueOrDefault(30);

This makes the fallback explicit and self-documenting. It also keeps the logic in one place, avoiding repeated if checks. If the default is the natural value for the type, the parameterless version is fine, but ?? is often just as concise.

In LINQ queries, GetValueOrDefault can be used to project nullable values to non-nullable ones:

var results = items.Select(x => x.SomeNullableInt.GetValueOrDefault());

Using GetValueOrDefault with LINQ and Collections

When working with collections of nullable value types, GetValueOrDefault simplifies transformations. For instance, to compute a sum of nullable integers while treating nulls as zero:

int?[] values = { 1, null, 3, null, 5 }; int total = values.Sum(v => v.GetValueOrDefault());

Without the projection, values.Sum() returns int?, so you would need another GetValueOrDefault() or ?? 0 to get a non-nullable int. Projecting through GetValueOrDefault makes the sum int directly. The method also works with Select to produce a sequence of non-nullable values:

IEnumerable<int> nonNull = values.Select(v => v.GetValueOrDefault());

This is particularly useful when downstream code expects non-nullable types.

C# Nullable<T>.GetValueOrDefault: Usage, Overloads, and Examples | RYUSLOG DEV