我只是偶然发现了这一点,我无法解释这一点。说我有那个代码:
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
}
}
现在featureType
始终为IFeature
类型,而不是参数类型featureDefinition
。有人可以解释原因吗?
我期待
featureType == featureDefinition.GetType()
是真的......
修改
以上是代码的完整工作示例。
现在我很清楚:参数是非通用的,因此始终是IFeature
类型。我想有一个小工作实例的原因:-P
感谢帮助人员!
答案 0 :(得分:4)
原因是TFeature
将是调用Activate函数的类型。这可以是IFeature
或实现它的任何类或接口。例如,像这样调用Activate是完全有效的:
Activate<IFeature>(feature);
在这种情况下,编译器使用类型IFeature
作为类型参数创建泛型方法Activate,结果是一个完全有效的方法来调用。但是,如果你称之为
Activate<Feature>(feature);
其中Feature
实现IFeature
,然后编译器当然会使用Feature
作为泛型类型参数,并且该方法可以再次调用。
当你只是调用像
这样的方法时,你可能会遇到困难Activate(feature);
在这种情况下,编译器使用他认为最适合的类型,基于编译器总是这样的静态分析。 不使用对象的运行时类型,因为编译器显然不知道这一点。相反,编译器尝试推断可用作类型参数的最不常见类型。
在这种情况下,编译器将检查静态类型feature
实现了哪些接口,如果它与条件匹配,则feature
的静态类型用作泛型类型参数。否则,编译器将抛出通用类型不清楚的错误消息。
例如,您始终可以通过显式覆盖静态类型来使编译器忘记静态类型:
object objFeature = feature;
Activate(objFeature);
现在,此代码将引发编译器错误,因为objFeature
的静态类型为Object
,并且这不符合应该实现IFeature
的约束。这与feature
的真实类型无关,而feature.GetType()
仅在运行时通过// 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>(...)
得到。
Inferrence samples:
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") }
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") }
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-04-04T21:23:13.331Z") }