Variance in Func<> arguments

[亡魂溺海] 提交于 2019-12-10 21:27:04

问题


I've been trying to do something like

Func<string, bool> f
Func<object, bool> F = f;

and the compiler raises the following error:

Cannot implicitly convert type 'System.Func<string,bool>' to 'System.Func<object,bool>'

However, we obviously can do object x = "123"


回答1:


Imagine if you had done this:

Func<string, bool> fStr = str => str.Length > 10;
Func<object, bool> fObj = fStr;

Well, according to the signature of fObj, you should be able to call it with any argument like this:

fObj(7);

Which is obviously invalid for fStr.




回答2:


The delegate type Func<in T, out TResult> is clearly contravariant in its first type argument T. A "func" that can take in any object can also take in a string, so a Func<object, X> "is a" Func<string, X>, so this is contravariance in the in type T.

You are trying to go the other way. That will only work if you happen to know that the run-time type is really a Func<object, bool>, and you will need explicit cast syntax to inform the compiler of your knowledge. If the run-time type is not correct, the explicit cast will fail.

Valid example:

Func<object, bool> f1 = XXX;
Func<string, bool> f2 = f1;                      // OK, implicit
Func<object, bool> f3 = (Func<object, bool>)f2;  // OK, explicit



回答3:


From MSDN

Implicit conversions: No special syntax is required because the conversion is type safe and no data will be lost. Examples include conversions from smaller to larger integral types, and conversions from derived classes to base classes.

Explicit conversions (casts): Explicit conversions require a cast operator. Casting is required when information might be lost in the conversion, or when the conversion might not succeed for other reasons. Typical examples include numeric conversion to a type that has less precision or a smaller range, and conversion of a base-class instance to a derived class.

You can't do that cast because you'll lose information. If you'll try it the other way, you could do it

 Func<object, bool> f = ....;
 Func<string, bool> F = f;

Because you won't lose information.

A simple example would be:

// This is ok. you can fit int in double
int some_int = 42;
double some_double = some_int;

// This is not ok. you might lose information
double some_double_2 = 42;
int some_int_2 = some_double_2;


// But you could do this, where the casts says: "Yep, I'm aware I might lose some
// information, but I'm an UBER programmer and want to do it anyways"
int some_int_3 = (int)some_double_2;

You can cast, or write your own default conversions. Have a look at the above MSDN link :)



来源:https://stackoverflow.com/questions/20169277/variance-in-func-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!