通用方法类型和方法参数不匹配
Generic method type and method parameter does not match
我只是无意中发现了这一点,我真的无法解释。说我有那个代码:
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
感谢大家的帮助!
原因是 TFeature
将是调用 Activate 函数的类型。这可以是 IFeature
或任何 class 或实现它的接口。例如,这样调用 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>(...)
我只是无意中发现了这一点,我真的无法解释。说我有那个代码:
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
感谢大家的帮助!
原因是 TFeature
将是调用 Activate 函数的类型。这可以是 IFeature
或任何 class 或实现它的接口。例如,这样调用 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>(...)