【问题标题】:Why Do I need to redeclare type constraint in generic subclass为什么我需要在泛型子类中重新声明类型约束
【发布时间】:2011-01-08 16:59:47
【问题描述】:

最近我尝试通过实现一个泛型接口来创建一个泛型子类。

public interface IModule<T> where T : DataBean { ..... }
public class Module<T> : IModule<T> where T : DataBean { .... } 

似乎我不能依赖基本接口中定义的任何 T 限制, 我需要自己重新声明它们。

MSDN 刚刚提供:

当使用子类泛型类型时 参数,你必须重复任何 基地规定的限制条件 子类级别的类级别。为了 例如,推导约束

为什么不能从基类/接口推断约束?

【问题讨论】:

  • 约束不需要复制,也可以选择使用可以转换为父约束类型的东西,让子更专业。
  • C# 4.0 规范几乎说了同样的话(第 13.4.3 节),但没有提供原因。
  • 如果我的子类中的泛型参数与基类中的泛型参数有矛盾的约束怎么办?
  • 那么你会得到一个编译错误

标签: c# generics inheritance type-constraints


【解决方案1】:

我想不出 c# 理论上不能复制约束的任何理由。但是记录在案的让我们显式复制(或扩充)它们的行为似乎是提高可用性的最简单方法。

public class A{}
public class B : A {}

public class X<T> where T: A {}
public class Y<T> : X<T> where T: B { }

在上面,请注意我不必显式复制Y&lt;T&gt; 上的约束,因为B总是A

现在让我们看看如果“编译器自动复制约束”会发生什么。假设我在没有约束的情况下定义了Y&lt;T&gt;,编译器会自动放置它们。我在很多代码中使用Y&lt;T&gt;。然后我更改了X&lt;T&gt; 声明的约束以包含一些新接口。

更改X&lt;T&gt; 声明的编译器错误出现在我使用 Y&lt;T&gt; 的站点!

按照 c# 编译器当前的工作方式,编译器错误在 X&lt;T&gt; 的用法上,如果我以破坏性的方式更改它,我会期望。

因此,虽然在某些情况下会很方便,但在其他情况下也会有些混乱。虽然这两种方法都是有效的方法,但我会假设(请注意,我无法读懂 c# 设计团队的想法)这是一个判断调用,而不是纯粹的技术调用。

我说“不纯粹是技术性的”,但我当然可以想象一些接口场景,其中验证是否满足所有约束会稍微简单一些,而不是生成满足所有必需继承约束的最简单约束。

【讨论】:

    【解决方案2】:

    标准 C# 团队智慧。声明应该是自我记录的。最重要的是,一个类型声明的更改不应该在不生成诊断的情况下改变不相关的其他类型的行为。设计中的 -100 分原则是对此的另一种看法。

    【讨论】:

      【解决方案3】:

      接口上的约束过于笼统,无法告诉编译器 Module 类应该具有哪些约束。例如,Module 类可能对 DataBean 的超类(继承类)具有约束。

      我不知道 C# 设计者的智慧。因为约束可能不同,我认为决定让开发人员明确声明约束,而不是让编译器做出假设。

      【讨论】:

        猜你喜欢
        • 2015-04-05
        • 2019-03-31
        • 1970-01-01
        • 2012-08-17
        • 2017-01-21
        • 1970-01-01
        • 2019-11-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多