What is the ?? syntax in C?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Despite the title, this question usually comes up in C# rather than in C, and it often refers to nullable syntax around arrays such as string?[]?. That notation is about whether the elements may be null, whether the array itself may be null, or both.
Read the ? From Left to Right
In C# nullable reference type syntax, the ? applies to the type immediately before it. For arrays, that creates several different meanings.
Consider these declarations:
They mean:
- '
string[]means the array itself is not intended to be null, and its elements are also non-nullable strings' - '
string?[]means the array exists, but each element may be null' - '
string[]?means the array reference itself may be null, but if the array exists its elements are non-nullable strings' - '
string?[]?means both the array and its elements may be null'
That is the key idea. The punctuation is just describing nullability at different layers of the type.
Why Arrays Make the Syntax Look Strange
Arrays introduce nesting. There is the outer reference to the array object, and then there are references stored inside the array. Nullable reference type annotations let you express nullability at both levels.
That is why string?[]? is not redundant. One ? applies to the element type and the other applies to the array reference.
A short example makes it easier to see:
In the first variable, the array exists and you can index it, but one element is allowed to be null. In the second variable, the array reference itself may be missing entirely.
This Is Different From the ?? Operator
Because the title mentions ??, it is also worth clarifying that C# has a separate null-coalescing operator named ??. That operator is unrelated to array-type annotations.
Here ?? means "use the left value unless it is null, otherwise use the right value." That is an operator in expressions, not a type annotation.
So there are two different topics that often get conflated:
- '
?in a type such asstring?[]?' - '
??in an expression such asname ?? "unknown"'
Nullable Context Must Be Enabled
These annotations are meaningful when nullable reference types are enabled in the project or file.
Or in a single file:
Without nullable context, the compiler does not interpret reference-type annotations in the same way, and many of the warnings that make the feature useful will not appear.
Why This Matters
The whole purpose of this syntax is to make nullability intent explicit. That helps the compiler warn you earlier about possible NullReferenceException scenarios.
For example, if a method returns string[]?, callers are being told that the whole array may be absent. If it returns string?[], callers know the array exists but some elements may still require checks.
Those are different contracts, and expressing that difference improves API clarity.
Common Pitfalls
A common mistake is reading string?[]? as if both ? markers say the same thing. They do not. One applies to elements and the other to the outer array reference.
Another mistake is confusing the nullable type annotation ? with the null-coalescing operator ??. They look related, but they live in different parts of the language.
People also often enable nullable reference types only partially and then wonder why the compiler does not warn consistently. The nullable context has to be enabled where the code is compiled.
Finally, do not assume that annotations alone prevent null bugs. They improve static analysis, but your code still needs correct checks and contracts.
Summary
- In C#,
?on a type marks nullability for the type immediately before it. - '
string?[]means nullable elements;string[]?means nullable array reference.' - '
string?[]?means both the array and its elements may be null.' - The
??operator is a different feature used in expressions. - Nullable reference type syntax is most useful when nullable context is enabled project-wide.

