为什么生成的代码与声明泛型类的两种方式不同

时间:2015-02-09 15:49:04

标签: c# generics

如果之前有人问过,请道歉;我发现很难找到合适的搜索字词。

为什么:

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);
}

4 个答案:

答案 0 :(得分:1)

这两个类提供相同的接口,但简单的事实是一个类是通用的而另一个类不会导致一些显着的差异。

看看两者是如何不同的最明显的方法是尝试使用反射从类名中实例化它们:在第一种情况下,您必须按名称获取泛型类,创建表示泛型类型实例的类型使用RuleContext作为其类型参数,然后只创建它的实例。在第二种情况下,单独一个名称就足以获得该类型。

一个更微妙的问题是,用两种不同类型实例化的IsUserAnonymousCondition<RuleCtx1>IsUserAnonymousCondition<RuleCtx2>的类型会有所不同。这意味着您无法将不同的IsUserAnonymousCondition<T>对象放入非通用容器中。

答案 1 :(得分:1)

在更实际的术语中,由于以下原因,它们在您的案例中不是同义词:

class StrinctRuleContext : RuleContext {}

有一个子类。我们可以拥有

var aStrinctRuleContext = new StrinctRuleContext();
var aRulesContext = new RuleContext();

我可以拥有

new IsUserAnonymousCondition<StrinctRuleContext>().Execute(aRulesContext)这是一个编译错误,即通用版本允许对其输入的 STRICTER 类型限制,而不是非泛型版本。也就是说,我可以自由地制作一个IsUserAnonymousCondition而不是“不能应对”#39;使用基本RulesContext类。

如果通用版本是进一步的子类,则通用版本还可以添加其他通用限制,即:

IsUserAnonymousConditionThatNeedsSomeExtraMojo : IsUserAnonymousCondition<T> where T : ISomeExtraMojo

将类型实现为RuleContext的不是。

答案 2 :(得分:0)

它们并不相同 - 尽管在您的情况下没有功能差异,因为T仅用作输入。

如果WhenCondition<T>的方法使用T作为输出,则存在差异:

public abstract class WhenCondition<T> : RuleCondition<T> where T : RuleContext
{
  protected abstract bool Execute(T ruleContext);
  protected abstract T GetContext();
}

现在你的两个类会有所不同,因为实际的返回类型IsUserAnonymousCondition.GetContext()在设计时是不知道的(编译器只知道它派生自RuleContext) ,但IsUserAnonymousCondition<T>.GetContext()的返回类型是已知的。

答案 3 :(得分:0)

在这种情况下:

WhenCondition<T> where T: RuleContext

T 派生自RuleContext。在编译时不知道实际类型。

这是:

WhenCondition<RuleContext>

现在并不重要,但想想这样做会有什么不同:

T GetSomething()

VS

RuleContext GetSomething()

第一个的返回类型可能与第二个不同。