为什么生成的代码与声明泛型的两种方式不同 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 的哪个不会。