Equality, Nullability & Dynamic
Value versus reference equality, Equals/GetHashCode, nullable types, immutability, var/dynamic/object, and type inference.
7 questions
MiddleTheoryVery commonWhat is Nullable<T> / int?, and how do you read its value safely?
What is Nullable<T> / int?, and how do you read its value safely?
Nullable<T> (shorthand int?) is a struct letting a value type also represent null. It exposes HasValue to test presence and Value to read it, which throws when empty. Safe reads use GetValueOrDefault() or ?? for a fallback.
Common mistakes
- ✗Reading
.Valuewithout checkingHasValue, which throwsInvalidOperationExceptionwhen empty - ✗Thinking
int?is a reference type rather than astructwrapping the value type - ✗Assuming
Nullable<T>works for reference types, whenTmust be a non-nullable value type
Follow-up questions
- →What does
GetValueOrDefault()return when the nullable has no value? - →How does lifting let arithmetic on two
int?operands produce anullresult?
JuniorTheoryCommonWhat does the program print (lines separated by spaces)?
What does the program print (lines separated by spaces)?
False True
Open full question →Common mistakes
- ✗Expecting
True True: for a class,==compares references by default, and two objects with equal fields are still two different objects. - ✗Expecting
False False:b = amakesblead to the objectaleads to, so the second comparison is between one object and itself.
Follow-up questions
- →What would the program print if
Spotwere astructand both lines useda.Equals(b)? - →Why does
==compare the text of twostringobjects instead of their references?
JuniorTheoryCommonWhat does the program print (lines separated by spaces)?
What does the program print (lines separated by spaces)?
-1 Anna
Open full question →Common mistakes
- ✗Expecting
-1 Bob:??=assigns only when the variable holdsnull, so the second line with??=leaves"Anna"in place. - ✗Expecting
0or an exception: withnullinname,name?.Lengthgivesnullwithout touchingLength, and??turns it into-1.
Follow-up questions
- →What would the program print if the first line were
string? name = "Bob";? - →What is the type of the expression
name?.Length, and why is it notint?
JuniorTheoryCommonWhat does var do, and is the variable it declares dynamically typed?
What does var do, and is the variable it declares dynamically typed?
var makes the compiler take the variable's type from its initial value: var x = 5; is exactly int x = 5;. The type is fixed at compile time and never changes, so the variable is statically typed.
Common mistakes
- ✗Expecting a
varvariable to change its type later: the compiler fixes the type from the initial value, so aftervar count = 10;a string put intocountdoes not compile. - ✗Expecting
varto cost time at run time: the type is chosen at compile time, and the program is the same as with the type written out.
Follow-up questions
- →Why must a
vardeclaration always have an initial value on the same line? - →When is
varrequired rather than optional in C# code?
MiddleTheoryCommonHow do == and Equals() differ for classes versus value types?
How do == and Equals() differ for classes versus value types?
For a class, both == and Equals() default to reference equality; value types default to value equality. == is a static, overloadable operator resolved at compile time; Equals is an overridable virtual method. string overrides both to compare values.
Common mistakes
- ✗Expecting
==on two distinct class instances with equal fields to return true by default - ✗Thinking
==is virtual and dispatches likeEquals, when it is a statically resolved operator - ✗Assuming
string ==compares references rather than the character sequence by value
Follow-up questions
- →Why should overriding
Equalsalso mean overridingGetHashCode? - →How can
==andEqualsgive different results on the same two operands?
MiddleTheoryOccasionalWhat does it mean that string is immutable, and why does it matter?
What does it mean that string is immutable, and why does it matter?
Immutable means an object's state cannot change after construction. Because string is immutable, every apparent mutation like Replace or ToUpper allocates a new string and leaves the original intact. For heavy in-loop edits use StringBuilder.
Common mistakes
- ✗Believing a string method like
Replacemodifies the original instead of returning a newstring - ✗Concatenating in a loop with
+, creating many short-lived strings instead of usingStringBuilder - ✗Confusing immutability of the string object with whether the variable holding it can be reassigned
Follow-up questions
- →How does string interning exploit immutability to share identical literals?
- →Why is an immutable type inherently safe to read from multiple threads without locking?
MiddleTheoryOccasionalHow do var, dynamic, and object differ in when types are resolved?
How do var, dynamic, and object differ in when types are resolved?
var is compile-time inference: the variable gets a concrete static type with full checking. object is the static base type of everything, so you must cast to call anything specific. dynamic defers member binding to runtime; an invalid member throws at runtime.
Common mistakes
- ✗Confusing
var(compile-time static type) withdynamic(runtime binding) - ✗Thinking
objectskips compile-time member checks, when it requires an explicit cast - ✗Assuming
dynamicerrors are caught at compile time rather than thrown at runtime
Follow-up questions
- →What runtime infrastructure does
dynamicuse to resolve member calls? - →Why does calling a method on an
objectvariable require a cast first?