问题
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