Start learning free

LESSON 90 OF 674 · CONDITIONAL STATEMENTS

Nullable value types: the ? after int

Lesson

An int in C# always holds a number. Zero, negative, huge — fine. But "no value at all"? A plain int simply cannot express it, and the compiler stops you the moment you try:

int score = null;   // rejected at compile time!
error CS0037: Cannot convert null to 'int' because it is a non-nullable value type

Yet "no value yet" is a real situation: a form field the user skipped, a search that found nothing, a high score before the first game. For those cases C# lets you add a question mark to the type. int? is a nullable value type — it holds either a real int or null:

int? score = 87;      // holds a value
int? missing = null;  // holds nothing — legal, thanks to the ?

Three tools for working with a nullable:

// 1. HasValue — is anything inside? (safe, never crashes)
score.HasValue        // True
missing.HasValue      // False

// 2. Value — the raw int inside (only when HasValue is True!)
score.Value           // 87

// 3. ?? — the value, or your fallback when null (safe)
missing ?? 0          // 0 — always a plain int, never null

?? is also how you get back to a plain int: writing int x = score; does not compile (error CS0266: Cannot implicitly convert type 'int?' to 'int') — the compiler forces you to decide the null case first, and int x = score ?? 0; is the idiomatic answer.


The trap:

.Value does NOT check for you. Calling it on an empty nullable compiles without a single complaint:

int? missing = null;
Console.WriteLine(missing.Value);   // compiles fine...

...and dies the moment it runs:

Unhandled exception. System.InvalidOperationException: Nullable object must have a value.
   at System.Nullable`1.get_Value()

The rule: reach for ?? (or check HasValue first) by default, and call .Value only when you have already proven a value is there.


Assignment
Follow the Coding Tutorial and try all three tools on a present and an absent value:

  • declare int? score = 87; and int? missing = null;,
  • print HasValue for each — the safe question, no crash either way,
  • print score.Value — safe here, because score certainly holds a value,
  • print each with the fallback ?? 0.

The exact expected output is:

score has value = True
missing has value = False
score value = 87
score or default = 87
missing or default = 0

Hint
Build each line with string concatenation, e.g. Console.WriteLine("score has value = " + score.HasValue); — C# prints booleans capitalized (True/False). When concatenating a ?? expression, wrap it in parentheses — "score or default = " + (score ?? 0) — because + binds tighter than ??.


STEP 1 OF 7
    Ctrl + Enter to check