How can I pass a delegate that takes a derived type argument for a delegate with a base type argument?

Consider the code:

public interface IGeneral {} public interface ISpecific : IGeneral {} public Func<IGeneral, String> Cast(Object specificFuncAsObject) { var generalFunc = specificFuncAsObject as Func<IGeneral, String>; Assert.IsNotNull(generalFunc); // <--- casting didn't work return generalFunc; } Func<ISpecific, String> specificFunc = specific => "Hey!"; var generalFunc = Cast(specificFunc); 

Is there any way to do such a casting job? I know that a general cannot be transferred to ISpecific in the general case. But in my specific situation, I would like to do something like this:

  Func<IGeneral, String> generalFunc = new Func<IGeneral, String>(general => specificFunc(general as ISpecific)); 

But having specificFunc as an Object and having an ISpecific type only through specificFuncAsObject.GetType()

+4
source share
2 answers

I believe this is not possible, think of the following case:

 class Base { } class DerivedA : Base { } class DerivedB : Base { } 

Using some methods:

 string DoSomething(DerivedA myDerived) { } 

Then you have the code:

 Func<DerivedA, string> functionA = DoSomething; // Let assume this cast is possible... Func<Base, string> functionBase = (Func<BaseB, string>) functionA; // At this point, the signature of the function that functionBase is assigned to // is actually `string DoSomething(DerivedA myDerived)` functionB(new DerivedB()); // If the cast is allowed, then passing a DerivedB should be allowed, but this makes // absolutely no sense because the function is expecting a DerivedA. 

What you can do is use the utility function to convert using the cast operator (or as if you want):

 Func<Base, string> Convert<T>(Func<T, string> function) where T : Base { return x => function(x as T); } 

And then do something like:

 Func<DerivedA, string> functionA = DoSomething; Func<Base, string> functionBase = Convert(functionA); 
+3
source

T (input type) in Func<T, TResult> contravariant, not covariant , so this is not possible. However, you can do the following:

 Func<ISpecific, String> specificFunc = specific => "Hey!"; Func<IGeneral, String> generalFunc = general => specificFunc((ISpecific)general); 

Or vice versa:

 Func<IGeneral, String> generalFunc = general => "Hey!"; Func<ISpecific, String> specificFunc = generalFunc; 
+8
source

Source: https://habr.com/ru/post/1502891/


All Articles