Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么结果代码与声明泛型类的两种方式不同_C#_Generics - Fatal编程技术网

C# 为什么结果代码与声明泛型类的两种方式不同

C# 为什么结果代码与声明泛型类的两种方式不同,c#,generics,C#,Generics,如果之前有人问过,请道歉;我发现很难找到合适的搜索词 原因是: public class IsUserAnonymousCondition<T> : WhenCondition<T> where T: RuleContext { protected override bool Execute( T ruleContext ) { ... } } public类IsUserAnonymousCondition:WhenConditi

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

原因是:

public class IsUserAnonymousCondition<T> : WhenCondition<T> where T: RuleContext
{
    protected override bool Execute( T ruleContext )
    {
        ...
    }
}
public类IsUserAnonymousCondition:WhenCondition where T:RuleContext
{
受保护的覆盖布尔执行(T规则上下文)
{
...
}
}
不同于:

public class IsUserAnonymousCondition : WhenCondition<RuleContext>
{
    protected override bool Execute( RuleContext ruleContext )
    {
        ...
    }
}
public类IsUserAnonymousCondition:WhenCondition
{
受保护的覆盖布尔执行(RuleContext RuleContext)
{
...
}
}
或者更确切地说;这两个编译不是相同的吗?如果没有,为什么没有

它们都是编译的,因此都应该重写相同的基方法

public abstract class WhenCondition<T> : RuleCondition<T> where T : RuleContext
{
  protected abstract bool Execute(T ruleContext);
}
公共抽象类WhenCondition:RuleCondition其中T:RuleContext
{
受保护的抽象bool-Execute(T-ruleContext);
}

它们不一样-尽管在您的案例中没有功能上的差异,因为
T
仅用作输入

如果条件有一个将T用作输出的方法时,

公共抽象类WhenCondition:RuleCondition其中T:RuleContext
{
受保护的抽象bool-Execute(T-ruleContext);
受保护的抽象T GetContext();
}
现在,您的两个类将不同,因为在设计时,
IsUserAnonymousCondition.GetContext()
的实际返回类型是未知的(编译器只知道它派生自
RuleContext
),但
IsUserAnonymousCondition.GetContext()
的返回类型是已知的。

在这种情况下:

WhenCondition<T> where T: RuleContext
现在这并不重要,但想想这样做会有什么不同:

T GetSomething()
vs


第一个类的返回类型可以不同于第二个类。

这两个类提供相同的接口,但一个类是泛型的,另一个是泛型的这一简单事实并不会导致一些显著的差异

要了解这两者的区别,最明显的方法是尝试使用反射从类名实例化它们:在第一种情况下,您必须按名称获取泛型类,创建一个表示泛型类型实例的类型,并使用
RuleContext
作为其类型参数,然后才创建它的实例。在第二种情况下,仅一个名称就足以获得类型


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

更实际地说,它们在您的情况下不是同义词,因为:

class StrinctRuleContext : RuleContext {}
有一个子类。然后我们就可以

var aStrinctRuleContext = new StrinctRuleContext();
var aRulesContext = new RuleContext();
我可以从那里得到什么

new IsUserAnonymousCondition().Execute(aruleContext)
这是一个编译错误,即通用版本允许对其输入进行比非通用版本更严格的类型限制。ie我可以自由创建一个IsUserAnonymousCondition,但不能“处理”基本RulesContext类

通用版本还保留了添加更多通用限制的能力,如果它是更进一步的子类,即:

IsUserAnonymousConditionThatNeedsSomeExtraMojo : IsUserAnonymousCondition<T> where T : ISomeExtraMojo
IsUserAnonymousCondition需要满足Extramojo:IsUserAnonymousCondition其中T:ISomeExtraMojo

将类型实现为RuleContext的过程中,哪一个没有。

实际上,第二个类与第一个类不同,不是泛型的。在您的示例中,这些类在运行时的行为可能相同,但您必须认识到泛型给您带来了许多编译时好处。您可以尝试使用最抽象的类型,甚至
对象
使您的类型尽可能通用,但从API的角度来看,这是一种可怕的体验。还有引用和值类型的装箱/拆箱问题……这很有意义。我太专注于当前场景,以及这两个变体(在我看来)将如何编译成相同的东西。当然没有,我现在明白了:-)
class StrinctRuleContext : RuleContext {}
var aStrinctRuleContext = new StrinctRuleContext();
var aRulesContext = new RuleContext();
IsUserAnonymousConditionThatNeedsSomeExtraMojo : IsUserAnonymousCondition<T> where T : ISomeExtraMojo