Glossary / Generic types

Generic types

Generic types parameterize classes, structs, interfaces, delegates, and methods over types, allowing reusable implementations with compile-time type safety. A constructed type such as List<string> specifies type arguments; the runtime and compiler enforce generic constraints and preserve type information, unlike object-based collections requiring casts and boxing.

Type parameters and construction

public sealed class Box<T>
{
    public T Value { get; }
    public Box(T value) => Value = value;
}

Type parameters can be used in members and nested types. Generic classes are invariant by default: IEnumerable<string> can be used as IEnumerable<object> through interface covariance, but List<string> is not a List<object>. Generic constraints restrict valid arguments and enable operations such as new T() or interface calls. Generic static fields are separate for each closed constructed type.

.NET generics are reified: runtime type information for generic arguments is retained. The CLR commonly uses shared native code for reference-type instantiations and specializes value-type instantiations, though implementation details vary. Generic code can avoid boxing when using constrained calls, but allocations can still occur through conversions and APIs.

API design

Use generics when operations preserve a relationship with the type parameter. Avoid unnecessary type parameters that callers cannot infer. Constraints should express real requirements. For public libraries, generic variance and nullability annotations affect usability and compatibility.

Interview questions

  1. What safety do generics add? Compile-time relationships and fewer casts/boxing compared with object collections.
  2. Are classes covariant by default? No; generic classes are invariant unless specific interface/delegate variance applies.
  3. Are generic arguments erased in .NET? No; generic type information is retained at runtime.
  4. Why separate static state per T? Each closed generic constructed type has its own static fields.
  5. How avoid boxing in generic code? Use constrained generic operations and typed APIs rather than object/interface conversions; measure.

References