Why does ? cause a conversion error while if-else does not?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The ternary operator ? : in C# (and similar languages) requires both branches to have a common type that the compiler can determine at compile time. If the true and false branches return different types with no implicit conversion between them, the compiler raises a type error. The if-else statement does not have this restriction because each branch is an independent statement — it does not need to produce a single result type. This difference in type resolution rules is the root cause of the conversion error.
The Problem in C#
Why the Ternary Operator Is Strict
The compiler does not consider the type of the variable being assigned to. It only looks at the two branches of the ternary expression to find a common type.
The Same Issue in Java
In Java, the ternary operator uses binary numeric promotion rules. If neither operand is convertible to the other, it is a compile error.
Nullable Types in C#
The ternary operator determines its result type as the common type of both branches. If one branch is int?, the result type is int?, even if the condition guarantees the non-null branch is selected.
TypeScript Ternary Behavior
TypeScript infers the ternary result as a union type. The compiler does not narrow based on the condition — it considers both branches possible.
Kotlin's when Expression
In Kotlin, if-else is also an expression, so it follows the same type resolution rules as the ternary operator in other languages.
How to Fix the Error
Common Pitfalls
- Assuming the ternary uses the target variable's type for resolution: The compiler determines the ternary's result type from its two branches only, ignoring the variable being assigned to.
double x = true ? 1 : "hello"fails becauseintandstringhave no common type, regardless ofxbeingdouble. - Confusing implicit widening with type compatibility:
inttodoubleworks because there is an implicit conversion.inttostringdoes not because there is no implicit conversion — you must call.ToString()explicitly. - Nullable confusion in C#:
true ? nonNullable : nullablereturns the nullable type. Assigning this to a non-nullable variable fails. The compiler cannot use the condition to determine which branch executes at compile time. - Forgetting that Kotlin's if-else is an expression: Unlike C# or Java, Kotlin's
if-elsefollows expression typing rules (same as ternary). Both branches must have a compatible type when used as an expression. - Using ternary for side effects instead of value production:
condition ? doA() : doB()is valid but misleading when the return values are discarded. Useif-elsefor side-effect-only branches for clarity.
Summary
- The ternary operator (
? :) is an expression that must produce a single result type from both branches - The compiler determines the result type from the two branches, not from the assignment target
if-elsestatements allow different types in each branch because they are independent assignments- Fix type errors by casting both branches to a common type, using
.ToString(), or switching toif-else - In Kotlin,
if-elseis also an expression and follows the same type resolution rules - Nullable types in the ternary make the result nullable, even if the condition guarantees non-null

