Type Members
Properties, indexers, extension methods, const vs readonly, ref/out, enums, and events.
9 questions
JuniorTheoryVery commonWhat is a property in C#, and how does it differ from a public field?
What is a property in C#, and how does it differ from a public field?
A property is a get/set accessor pair giving controlled access to state. An auto-property { get; set; } makes the compiler generate a hidden backing field. Unlike a public field, a property is a method pair, so you can add validation or logic in set, expose it read-only, or change the implementation later without breaking callers.
Common mistakes
- ✗Believing a property compiles to the same thing as a field, so swapping one for the other is binary-compatible
- ✗Thinking an auto-property has no backing field, when the compiler silently generates one
- ✗Assuming a property must expose both
getandsetrather than being able to omit the setter
Follow-up questions
- →How do you back a property with custom validation instead of an auto-property?
- →What does an expression-bodied or
init-only property change about access?
JuniorTheoryCommonWhat is the difference between const and readonly fields in C#?
What is the difference between const and readonly fields in C#?
A const is a compile-time constant: it must be assigned a literal at declaration, is implicitly static, and its value is baked directly into every caller's compiled code. A readonly field is set once at runtime — either at declaration or in a constructor — can differ per instance, and may hold a non-literal value. Changing a const requires recompiling all consumers; a readonly does not.
Common mistakes
- ✗Assuming changing a
constin a library propagates to callers without recompiling them - ✗Thinking a
readonlyfield is implicitlystaticlike aconst, rather than instance-level by default - ✗Trying to assign a
consta non-literal or method-call value, which the compiler rejects
Follow-up questions
- →Why can a
readonlyreference-type field still have its target object mutated? - →When does inlining a
constinto callers cause a versioning bug across assemblies?
MiddleTheoryCommonWhat is the difference between ref and out parameters in C#?
What is the difference between ref and out parameters in C#?
Both pass an alias to the caller's variable rather than a copy, so the method reads and writes the same storage. A ref argument must be initialized before the call, since the method may read it. An out argument need not be initialized beforehand, but the method MUST assign it before returning. Use out to return extra values; use ref for two-way exchange.
Common mistakes
- ✗Thinking
reforoutpasses a copy, so caller changes are lost — they alias the same storage - ✗Forgetting that the method must definitely assign every
outparameter before any return path - ✗Believing an
outargument must be initialized by the caller, when onlyrefrequires that
Follow-up questions
- →How does
out vardeclaration inline a variable at the call site? - →Why can't an
asyncmethod or iterator declareref/outparameters?
JuniorTheoryOccasionalWhat is an enum in C#, and what does the [Flags] attribute add?
What is an enum in C#, and what does the [Flags] attribute add?
An enum is a named set of integral constants. Its underlying type defaults to int, and the first member defaults to value 0 unless you assign explicit values. [Flags] marks the enum as a bit field, so members assigned distinct powers of two can be combined with bitwise | and tested with &, and ToString then formats combinations as a comma-separated list.
Common mistakes
- ✗Forgetting that the default first member is 0, so a missing zero value makes the default state unrepresentable
- ✗Using sequential values 1, 2, 3 with
[Flags]instead of powers of two, so combinations overlap - ✗Believing
[Flags]itself enables bitwise math, when any enum already supports|and&
Follow-up questions
- →How do you change an enum's underlying type to
byteorlong, and why would you? - →Why is reserving an explicit
None = 0member recommended for a[Flags]enum?
MiddleTheoryOccasionalWhat is an extension method in C#, and how is one declared?
What is an extension method in C#, and how is one declared?
An extension method is a static method in a static class whose first parameter is prefixed with this, like this T x. The compiler lets you call it as if it were an instance method on T, so you can add methods to a type — including an interface like IEnumerable<T> — without modifying or subclassing it. LINQ operators are extension methods, found by using the namespace.
Common mistakes
- ✗Thinking an extension method can access the extended type's private members like a real instance method
- ✗Believing an extension method overrides or shadows an instance method of the same name — the instance method wins
- ✗Forgetting the
usingfor the method's namespace, so the call doesn't resolve
Follow-up questions
- →What happens when an instance method and an extension method have the same signature?
- →Why does extending
IEnumerable<T>make a method available on every collection type?
MiddleTheoryOccasionalWhy use StringBuilder instead of + concatenation in a loop?
Why use StringBuilder instead of + concatenation in a loop?
Because string is immutable, each + in a loop cannot modify the existing string — it allocates a brand-new string and copies all prior characters, so concatenating n times is O(n²) work and floods the GC with throwaway strings. StringBuilder holds a mutable, growable buffer and appends in place, making the build O(n). Call ToString() once at the end to materialize the result.
Common mistakes
- ✗Believing
+mutates the existing string instead of allocating a new one each time - ✗Thinking concatenation in a loop is O(n) rather than O(n²) from repeated full copies
- ✗Using
StringBuilderfor a couple of fixed concatenations, where plain+is simpler and as fast
Follow-up questions
- →How does setting an initial capacity on
StringBuilderreduce reallocations? - →When does the compiler optimize a few
+operations into a singleString.Concatcall?
SeniorTheoryOccasionalHow does an event restrict access compared to a plain delegate field?
How does an event restrict access compared to a plain delegate field?
An event wraps a delegate field but exposes only += and -= to outside code, so subscribers can attach and detach handlers but cannot invoke the delegate or overwrite the whole list. Only the declaring type may raise the event or reassign it. This encapsulates the publisher/subscriber pattern: it prevents a subscriber from clearing other subscribers or firing the event on the publisher's behalf.
Common mistakes
- ✗Thinking outside code can invoke or reassign an
eventlike a public delegate field - ✗Confusing which side gets
+=/-=versus invocation — subscribers add/remove, only the owner raises - ✗Believing
eventadds threading or async behavior rather than only access encapsulation
Follow-up questions
- →How do custom
add/removeaccessors let you control an event's subscription storage? - →Why is raising an event into a local copy of the delegate the thread-safe pattern?
JuniorTheoryRareWhat does the partial keyword do for a class in C#?
What does the partial keyword do for a class in C#?
partial lets a single class, struct, interface, or method be split across multiple source files, which the compiler merges into one type at build time. Every part must use partial and share the same name and namespace. Its main use is keeping machine-generated code — designer files or source-generator output — in a separate file from hand-written code, so regeneration never overwrites your edits.
Common mistakes
- ✗Thinking
partialmerges differently named classes, when every part must share the same name - ✗Believing the parts can live in different namespaces, when they must all match
- ✗Assuming
partialproduces multiple types at runtime, when the compiler emits exactly one
Follow-up questions
- →How does a
partialmethod behave when no part provides its body? - →Why do source generators rely on
partialto extend a user-written class safely?
MiddleTheoryRareWhat is an indexer in C#, and how does it relate to a property?
What is an indexer in C#, and how does it relate to a property?
An indexer lets instances of a type be accessed with [] bracket syntax, as in obj[i], the way an array is. It is declared with the this keyword, like public T this[int i] { get; set; }. An indexer is essentially a property that takes parameters: it has get/set accessors but no name, and it can be overloaded on different parameter types such as this[string key].
Common mistakes
- ✗Thinking an indexer must wrap a real array, when its
get/setbody can compute or look up anything - ✗Believing a type can have only one indexer, when indexers can be overloaded by parameter type
- ✗Assuming an indexer is read-only, when it can declare a
setaccessor like any property
Follow-up questions
- →How would you add a second indexer keyed by
stringalongside anintone? - →What member name does an indexer compile to in the generated IL?