Bird
Raised Fist0
C Sharp (C#)programming~5 mins

Contravariance with in keyword in C Sharp (C#) - Cheat Sheet & Quick Revision

Choose your learning style10 modes available
Recall & Review
beginner
What does the in keyword mean in C# generic interfaces?
The in keyword marks a generic type parameter as contravariant, allowing you to use a less derived type than originally specified. It means you can pass a more general type where a more specific type is expected.
Click to reveal answer
beginner
Explain contravariance in simple terms.
Contravariance lets you use a more general type instead of a more specific one. For example, if a method expects a Cat, contravariance lets you pass an Animal instead, because Animal is more general than Cat.
Click to reveal answer
intermediate
Which C# interfaces commonly use the in keyword for contravariance?
Interfaces like IComparer<T> and IEqualityComparer<T> use the in keyword to allow contravariance on their generic type parameters.
Click to reveal answer
intermediate
Can you use the in keyword on generic type parameters used as return types?
No. The in keyword can only be used on generic type parameters that are used as input (method parameters). It cannot be used on return types because contravariance applies only to input positions.
Click to reveal answer
intermediate
What is the difference between covariance and contravariance in C#?
Covariance (marked with out) allows using a more derived type than originally specified, usually for return types. Contravariance (marked with in) allows using a less derived type, usually for input parameters.
Click to reveal answer
What does the in keyword specify in a generic interface?
AGenerates a new type parameter
BCovariance - allows more derived types as output
CContravariance - allows less derived types as input
DInvariant - no variance allowed
Which of these interfaces uses contravariance with in?
AIEnumerable&lt;T&gt;
BIComparer&lt;T&gt;
CIList&lt;T&gt;
DFunc&lt;T&gt;
Can a contravariant type parameter be used as a return type in a method?
ANo, never
BOnly if marked with <code>out</code>
CYes, always
DOnly in abstract classes
If a method expects IComparer<Cat>, which can you pass due to contravariance?
AIComparer&lt;Dog&gt;
BIComparer&lt;Tiger&gt;
CIComparer&lt;Cat&gt;
DIComparer&lt;Animal&gt;
What keyword marks covariance in C# generics?
Aout
Bin
Cref
Dvar
Describe contravariance and how the in keyword enables it in C# generics.
Think about how you can use a more general type where a specific type is expected.
You got /4 concepts.
    Explain why contravariant type parameters cannot be used as return types in methods.
    Consider the direction of data flow for contravariant types.
    You got /4 concepts.

      Practice

      (1/5)
      1.

      What does the in keyword specify when used in a generic interface declaration like IComparer?

      easy
      A. It allows the type parameter to be used only as a return type.
      B. It marks the type parameter as contravariant, allowing it to accept less derived types.
      C. It restricts the type parameter to value types only.
      D. It marks the type parameter as covariant, allowing it to return more derived types.

      Solution

      1. Step 1: Understand the role of in keyword in generics

        The in keyword declares a generic type parameter as contravariant, meaning it can accept arguments of less derived types safely.
      2. Step 2: Contrast with covariance

        Covariance (using out) allows returning more derived types, while contravariance (using in) allows accepting less derived types as input.
      3. Final Answer:

        It marks the type parameter as contravariant, allowing it to accept less derived types. -> Option B
      4. Quick Check:

        in means contravariant = It marks the type parameter as contravariant, allowing it to accept less derived types. [OK]
      Hint: Remember: 'in' means input, contravariant accepts less derived types [OK]
      Common Mistakes:
      • Confusing 'in' with covariance (out keyword)
      • Thinking 'in' restricts to value types
      • Assuming 'in' applies to return types
      2.

      Which of the following is the correct syntax to declare a contravariant generic interface IProcessor with type parameter T?

      ?
      easy
      A. interface IProcessor { void Process(T item); }
      B. interface IProcessor { void Process(T item); }
      C. interface IProcessor<T> { T Process(); }
      D. interface IProcessor { T Process(); }

      Solution

      1. Step 1: Identify contravariant syntax

        Contravariance uses in keyword before the type parameter in interface declaration.
      2. Step 2: Check method usage

        Contravariant type parameters can only be used as input parameters, not as return types. So method must accept T as parameter, not return it.
      3. Final Answer:

        interface IProcessor<in T> { void Process(T item); } -> Option A
      4. Quick Check:

        Contravariant = in + input parameter only = interface IProcessor<in T> { void Process(T item); } [OK]
      Hint: Use 'in' with input parameters only, no returns [OK]
      Common Mistakes:
      • Using 'out' instead of 'in' for contravariance
      • Returning type T in contravariant interface
      • Omitting 'in' keyword
      3.

      Consider the following code snippet:

      interface IConsumer { void Consume(T item); }
      
      class Animal { }
      class Dog : Animal { }
      
      IConsumer<Animal> animalConsumer = new Consumer();
      IConsumer<Dog> dogConsumer = animalConsumer;

      What will happen when this code runs?

      medium
      A. It throws a runtime exception.
      B. It causes a compile-time error because types are incompatible.
      C. It compiles and runs successfully due to contravariance.
      D. It compiles but causes a runtime error.

      Solution

      1. Step 1: Understand contravariance assignment

        Contravariance allows assigning IConsumer<Animal> to IConsumer<Dog> because Dog is more derived than Animal.
      2. Step 2: Check code behavior

        The assignment IConsumer<Dog> dogConsumer = animalConsumer; is valid and compiles because of in keyword on T.
      3. Final Answer:

        It compiles and runs successfully due to contravariance. -> Option C
      4. Quick Check:

        Contravariance allows assignment from base to derived = It compiles and runs successfully due to contravariance. [OK]
      Hint: Contravariant interface allows base-to-derived assignment [OK]
      Common Mistakes:
      • Thinking assignment is invalid due to type mismatch
      • Confusing contravariance with covariance
      • Expecting runtime errors
      4.

      Given this interface declaration:

      interface IHandler { void Handle(T item); }

      Which of the following code snippets will cause a compile-time error?

      ?
      medium
      A. IHandler<object> handler = new Handler<string>();
      B. IHandler<string> handler = new Handler<object>();
      C. IHandler<string> handler = new Handler<string>();
      D. IHandler<object> handler = new Handler<object>();

      Solution

      1. Step 1: Recall contravariance assignment rules

        Contravariance allows assignment from less derived to more derived generic types, e.g., IHandler<Animal> to IHandler<Dog>.
      2. Step 2: Analyze each option

        IHandler<object> handler = new Handler<string>(); tries to assign IHandler<string> to IHandler<object>, which is from more derived to less derived generic types, invalid for contravariance.
      3. Final Answer:

        IHandler<object> handler = new Handler<string>(); -> Option A
      4. Quick Check:

        Contravariance disallows assigning derived generic to base generic = IHandler<object> handler = new Handler<string>(); [OK]
      Hint: Contravariant assignment reverses subtype direction [OK]
      Common Mistakes:
      • Assigning derived generic to base generic incorrectly
      • Confusing contravariance with covariance
      • Ignoring compile-time type safety
      5.

      You have these interfaces and classes:

      interface IProcessor { void Process(T item); }
      class Vehicle { }
      class Car : Vehicle { }
      
      class VehicleProcessor : IProcessor<Vehicle> {
          public void Process(Vehicle item) { Console.WriteLine("Processing vehicle"); }
      }

      Which assignment is valid and why?

      ?
      hard
      A. IProcessor<Vehicle> vehicleProcessor = new VehicleProcessor(); // Invalid because of contravariance
      B. IProcessor<Car> carProcessor = new IProcessor<Vehicle>(); // Invalid because of covariance
      C. IProcessor<Vehicle> vehicleProcessor = new IProcessor<Car>(); // Valid because Car is derived
      D. IProcessor<Car> carProcessor = new VehicleProcessor(); // Valid because of contravariance

      Solution

      1. Step 1: Understand contravariance assignment direction

        Contravariance allows assigning IProcessor<Vehicle> to IProcessor<Car> because Car is derived from Vehicle.
      2. Step 2: Evaluate each option

        IProcessor<Car> carProcessor = new VehicleProcessor(); // Valid because of contravariance assigns VehicleProcessor (implements IProcessor<Vehicle>) to IProcessor<Car> variable, which is valid due to contravariance.
      3. Final Answer:

        IProcessor<Car> carProcessor = new VehicleProcessor(); // Valid because of contravariance -> Option D
      4. Quick Check:

        Contravariance allows base to derived assignment = IProcessor<Car> carProcessor = new VehicleProcessor(); // Valid because of contravariance [OK]
      Hint: Contravariant interface allows base type instance for derived type variable [OK]
      Common Mistakes:
      • Confusing covariance and contravariance directions
      • Trying to assign interface instances incorrectly
      • Ignoring inheritance hierarchy in assignments
      Recommended

      Ready to prove it?

      Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

      10 questions~5 mineasy hard