Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Co/contravariance with Func<in T1, out TResult> as parameter

Assume I have an interface such as

public interface IInterface<in TIn, out TOut> {
  IInterface<TIn, TOut> DoSomething(TIn input);
}

TIn being contra-variant, and TOut being co-variant.

Now, I want callers to be able to specify some function to be executed on the input's value, so naïvely I would add the following method to the interface:

IInterface<TIn, TOut> DoSomethingWithFunc(Func<TIn, TOut> func);

which … does not work. TIn is now required to be covariant, and TOut contravariant.

I understand, that I cannot use covariant generic types as input for methods, but I thought I could use them in a nested generic type which itself specifies the variance (Func<in T1, out TResult>).

I tried creating a new delegate type with co-/contravariant types and change the interface to accept an argument of this type, to no avail (same error).

public delegate TOut F<in TDlgIn, out TDlgOut>(TDlgIn input);

public interface IInterface<in TIn, out TOut> {
  IInterface<TIn, TOut> DoSomethingWithFunc(F<TIn, TOut> func);
}

I there a way I can make the compiler happy? Is this even possible (for instance with other nested types, or additional generic arguments)? If not, why not?

like image 709
knittl Avatar asked Feb 18 '16 11:02

knittl


1 Answers

This would not be safe since you could then use it to do:

public class Id<I, O> : IInterface<I, O>
{
    private Func<I, O> f;
    public Id(Func<I, O> f) { this.f = f; }
    public IInterface<I, O> DoSomething(I i) { this.f(i); return this; }
    public IInterface<I, O> DoSomethingWithFunc(Func<I, O> newF) {
        this.f = newF;
        return this;
    }
}

and then

Func<Animal, string> fa;
IInterface<object, string> oi = new Id<object, string>(_ => "");
Interface<Monkey, string> mi = oi;  //safe
IInterface<Monkey, string> mi2 = mi.DoSomethingWithFunc(fa);
oi.DoSomething("not an animal!");

at this point you will have passed a string to an Func<Animal, string>.

like image 135
Lee Avatar answered Oct 26 '22 21:10

Lee