为什么生成的代码与声明泛型的两种方式不同 class
Why does resulting code differ, from two ways of declaring a generic class
如果之前有人问过这个问题,我深表歉意;我发现很难找到合适的搜索词。
为什么是:
public class IsUserAnonymousCondition<T> : WhenCondition<T> where T: RuleContext
{
protected override bool Execute( T ruleContext )
{
...
}
}
不同于:
public class IsUserAnonymousCondition : WhenCondition<RuleContext>
{
protected override bool Execute( RuleContext ruleContext )
{
...
}
}
或者说;这两个编译不完全一样吗?如果没有,为什么不呢?
它们都可以编译,因此应该都覆盖相同的基本方法。
public abstract class WhenCondition<T> : RuleCondition<T> where T : RuleContext
{
protected abstract bool Execute(T ruleContext);
}
它们不一样 - 虽然在您的情况下没有功能差异,因为 T
仅用作输入。
不同之处在于,如果 WhenCondition<T>
有一个使用 T
作为 输出的方法:
public abstract class WhenCondition<T> : RuleCondition<T> where T : RuleContext
{
protected abstract bool Execute(T ruleContext);
protected abstract T GetContext();
}
现在你的两个 类 会有所不同,因为 actual return 类型的 IsUserAnonymousCondition.GetContext()
在设计时是未知的(编译器只知道它派生自 RuleContext
),但是 IsUserAnonymousCondition<T>.GetContext()
的 return 类型是已知的。
在这种情况下:
WhenCondition<T> where T: RuleContext
T
是 或 派生自 RuleContext
。实际类型在编译时未知。
这里是:
WhenCondition<RuleContext>
现在没什么大不了的,但是想想这样做会有什么不同:
T GetSomething()
对比
RuleContext GetSomething()
第一个的 return 类型可以与第二个不同。
这两个 class 提供了相同的界面,但是一个 class 是通用的而另一个是通用的这一简单事实并没有导致一些显着差异。
查看两者不同之处的最明显方法是尝试使用反射从 class 名称实例化它们:在第一种情况下,您必须通过以下方式获得通用 class name,用 RuleContext
作为类型参数创建一个表示泛型类型实例的类型,然后才创建它的实例。在第二种情况下,仅名称就足以获得类型。
一个更微妙的问题是IsUserAnonymousCondition<RuleCtx1>
和IsUserAnonymousCondition<RuleCtx2>
用两种不同类型实例化的类型会不同。这意味着您无法将不同的 IsUserAnonymousCondition<T>
对象放入非通用容器中。
在更实际的情况下,由于以下原因,它们在您的情况下不是同义词:
class StrinctRuleContext : RuleContext {}
有一个子class。然后我们可以
var aStrinctRuleContext = new StrinctRuleContext();
var aRulesContext = new RuleContext();
从哪里可以得到
new IsUserAnonymousCondition<StrinctRuleContext>().Execute(aRulesContext)
这是一个编译错误,即通用版本比非通用版本允许对其输入进行 STRICTER 类型限制。也就是说,我可以自由地使用基础 RulesContext class.
来创建 IsUserAnonymousCondition 而不是 'cope'
通用版本还保留了添加进一步通用限制的能力,如果它被进一步子classed,即:
IsUserAnonymousConditionThatNeedsSomeExtraMojo : IsUserAnonymousCondition<T> where T : ISomeExtraMojo
当然,将类型实现为 RuleContext 的哪个不会。
如果之前有人问过这个问题,我深表歉意;我发现很难找到合适的搜索词。
为什么是:
public class IsUserAnonymousCondition<T> : WhenCondition<T> where T: RuleContext
{
protected override bool Execute( T ruleContext )
{
...
}
}
不同于:
public class IsUserAnonymousCondition : WhenCondition<RuleContext>
{
protected override bool Execute( RuleContext ruleContext )
{
...
}
}
或者说;这两个编译不完全一样吗?如果没有,为什么不呢?
它们都可以编译,因此应该都覆盖相同的基本方法。
public abstract class WhenCondition<T> : RuleCondition<T> where T : RuleContext
{
protected abstract bool Execute(T ruleContext);
}
它们不一样 - 虽然在您的情况下没有功能差异,因为 T
仅用作输入。
不同之处在于,如果 WhenCondition<T>
有一个使用 T
作为 输出的方法:
public abstract class WhenCondition<T> : RuleCondition<T> where T : RuleContext
{
protected abstract bool Execute(T ruleContext);
protected abstract T GetContext();
}
现在你的两个 类 会有所不同,因为 actual return 类型的 IsUserAnonymousCondition.GetContext()
在设计时是未知的(编译器只知道它派生自 RuleContext
),但是 IsUserAnonymousCondition<T>.GetContext()
的 return 类型是已知的。
在这种情况下:
WhenCondition<T> where T: RuleContext
T
是 或 派生自 RuleContext
。实际类型在编译时未知。
这里是:
WhenCondition<RuleContext>
现在没什么大不了的,但是想想这样做会有什么不同:
T GetSomething()
对比
RuleContext GetSomething()
第一个的 return 类型可以与第二个不同。
这两个 class 提供了相同的界面,但是一个 class 是通用的而另一个是通用的这一简单事实并没有导致一些显着差异。
查看两者不同之处的最明显方法是尝试使用反射从 class 名称实例化它们:在第一种情况下,您必须通过以下方式获得通用 class name,用 RuleContext
作为类型参数创建一个表示泛型类型实例的类型,然后才创建它的实例。在第二种情况下,仅名称就足以获得类型。
一个更微妙的问题是IsUserAnonymousCondition<RuleCtx1>
和IsUserAnonymousCondition<RuleCtx2>
用两种不同类型实例化的类型会不同。这意味着您无法将不同的 IsUserAnonymousCondition<T>
对象放入非通用容器中。
在更实际的情况下,由于以下原因,它们在您的情况下不是同义词:
class StrinctRuleContext : RuleContext {}
有一个子class。然后我们可以
var aStrinctRuleContext = new StrinctRuleContext();
var aRulesContext = new RuleContext();
从哪里可以得到
new IsUserAnonymousCondition<StrinctRuleContext>().Execute(aRulesContext)
这是一个编译错误,即通用版本比非通用版本允许对其输入进行 STRICTER 类型限制。也就是说,我可以自由地使用基础 RulesContext class.
通用版本还保留了添加进一步通用限制的能力,如果它被进一步子classed,即:
IsUserAnonymousConditionThatNeedsSomeExtraMojo : IsUserAnonymousCondition<T> where T : ISomeExtraMojo
当然,将类型实现为 RuleContext 的哪个不会。