问题
I just stumbled over that and I can't really explain that. Say I have that code:
public interface IFeature { }
public class FeatureA : IFeature { }
class Program
{
static void Main(string[] args)
{
var feature = new FeatureA();
Load(feature);
}
private static void Load(IFeature featureDefinition)
{
Activate(featureDefinition);
}
private static void Activate<TFeature>(TFeature featureDefinition) where TFeature : IFeature
{
var featureType = typeof(TFeature);
var sameType = featureType == featureDefinition.GetType();
// sameType == false
}
}
Now featureType
is always of type IFeature
and not of the type of the parameter featureDefinition
. Can someone explain why?
I expected
featureType == featureDefinition.GetType()
to be true...
edit:
So above is a complete working example of the code.
Now it's quite clear to me: The parameter is non generic, thus always of type IFeature
. I guess there is a reason for a small working example :-P
Thanks for the help guys!
回答1:
Thereason is that TFeature
will be the type with that the Activate function has been called. This can be IFeature
or any class or interface implementing it. For example, it is perfectly valid to call Activate like that:
Activate<IFeature>(feature);
In that case, the compiler creates the generic method Activate using the type IFeature
as type parameter and the result is a method that is perfectly valid to call. However, if you call it like
Activate<Feature>(feature);
where Feature
implements IFeature
, then the compiler will of course use Feature
as generic type parameter and again the method is valid to call.
You might have difficulties what happens when you just call the method like
Activate(feature);
In that case, the compiler uses the type that he thinks fits best, based on static analysis as compilers always do. It is not using the runtime type of the object since this is obviously not known to the compiler. Rather, the compiler tries to infer the least common type that can be used as a type parameter.
In this case, the compiler will check what interfaces are implemented by the static type of feature
and if it matches the conditions, the static type of feature
is used as generic type parameter. Otherwise, the compiler will throw an error message that the generic type is unclear.
For example, you can always make the compiler forget about the static type by explicitly overriding it:
object objFeature = feature;
Activate(objFeature);
Now, this code will raise a compiler error since the static type of objFeature
is Object
and this does not fulfill the constraint that it should be implementing IFeature
. This is independent on the true type of feature
which you only get at runtime through feature.GetType()
.
Inferrence samples:
// typeof(TFeature) inside Activate returning `IFeature`:
IFeature f = new FeatureImpl();
Activate(f); // compiled into Activate<IFeature>(...)
// FeatureImpl:FeatureBase:IFeature
// typeof(TFeature) inside Activate returning `FeatureImpl`:
var f1 = new FeatureImpl();
Activate(f1); // compiled into Activate<FeatureImpl>(...)
FeatureBase f2 = new FeatureImpl();
Activate(f2); // compiled into Activate<FeatureBase>(...)
来源:https://stackoverflow.com/questions/33407940/generic-method-type-and-method-parameter-does-not-match