Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

140
Views
Contravariance invalid when using interface's delegate as a parameter type

Consider the contravariant interface definition with a delegate:

public interface IInterface<in TInput>
{
    delegate int Foo(int x);
    
    void Bar(TInput input);
    
    void Baz(TInput input, Foo foo);
}

The definition of Baz fails with an error:

CS1961
Invalid variance: The type parameter 'TInput' must be covariantly valid on 'IInterface<TInput>.Baz(TInput, IInterface<TInput>.Foo)'. 'TInput' is contravariant.

My question is why? On first glance this should be valid, as the Foo delegate has nothing to do with TInput. I don't know if it's the compiler being overly conservative or if I'm missing something.

Note that normally you wouldn't declare a delegate inside an interface, in particular this doesn't compile on versions older than C# 8, since a delegate in an interface needs default interface implementations.

Is there a way to break the type system if this definition was allowed, or is the compiler conservative?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

I am not sure if this is co- versus contravariance problem.

  1. The Foo delegate is not a member of the interface. It is a nested type declaration.
  2. IInterface<A>.Foo and IInterface<B>.Foo are two different types.
  3. This makes the foo parameter of two different IInterface<T>.Baz methods (with T = A and B) incompatible.
  4. Therefore you cannot substitute a IInterface<A> for a IInterface<B> or vice-versa (no matter what the inheritance relationship between A and B is.
  5. Conclusion: IInterface<T> cannot be variant (neither co- nor contra-).

Resolution:

  • Move the delegate to the top level (in the body of a namespace). It is a type declaration, so, it does not need to be embedded.
  • Or embed it in a type with no type parameter. E.g., you could create a non-generic IInterface for this (and keep your generic one).

But @EricLippert certainly knows better.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!