C#不允许结构派生自类,但是所有ValueTypes都派生自Object。这种区别在哪里?
CLR如何处理此问题?
C#不允许结构派生自类
您的陈述不正确,因此造成混淆。C# 确实 允许结构派生自类。所有结构都派生自同一类System.ValueType,该类派生自System.Object。并且所有枚举都派生自System.Enum。
更新:一些(现在已删除)评论中有些混乱,有必要澄清。我会问一些其他问题:
结构是否衍生自基本类型?
显然是的。我们可以通过阅读规范的第一页看到这一点:
所有C#类型(包括基本类型(例如int和double))都从单个根对象类型继承。
现在,我注意到规范在这里夸大了这种情况。指针类型不是从对象派生的,并且接口类型和类型参数类型的派生关系比此草图指示的要复杂。但是,很明显,所有结构类型都是从基本类型派生的。
我们还有其他方法可以知道结构类型是从基本类型派生的吗?
当然。结构类型可以覆盖ToString。如果不是其基本类型的虚拟方法,那么它覆盖什么?因此,它必须具有基本类型。该基本类型是一个类。
ToString
我可以从自己选择的类中派生用户定义的结构吗?
显然没有 这并不意味着结构不是从类派生的 。结构派生自一个类,从而继承该类的可继承成员。实际上, 需要 从特定的类派生Enum结构:需要枚举,必须从Enum派生,必须从派生结构ValueType。由于这些是 必需的 ,因此C#语言 禁止 您在代码中声明派生关系。
Enum
ValueType
为什么要禁止它?
当 需要 某种关系 时 ,语言设计者可以选择:(1)要求用户键入所需的咒语,(2)将其设为可选,或(3)禁止它。每个都有优缺点,C#语言设计师根据每个细节都选择了不同的内容。
例如,const字段必须是静态的,但禁止说它们是因为这样做首先是无意义的转义,其次意味着存在非静态const字段。但是,即使开发人员别无选择,重载运算符也必须标记为静态。开发人员很难相信操作符重载是实例方法。这消除了用户可能会认为“静态”暗示“虚拟”也是可能的担忧。
在这种情况下,要求用户说他们的结构是从ValueType派生的,这似乎仅仅是多余的词,这意味着该结构 可以 从另一种类型派生。为了消除这两个问题,C# 禁止 在代码中声明结构是从基本类型派生的,尽管很明显。
同样,所有委托类型都源自MulticastDelegate,但是C#要求您 不要 这样说。
MulticastDelegate
因此,现在我们已经确定 C# 中的 所有结构都源自一个类 。
从类 继承 和 继承 之间有什么关系? __
许多人对C#中的继承关系感到困惑。继承关系非常简单:如果结构,类或委托类型D是从类类型B派生的,那么B的可继承成员也是D的成员。就这么简单。
当我们说一个结构是从ValueType派生出来的时,对于继承是什么意思?简单地说,ValueType的所有可继承成员也是该结构的成员。例如,这就是结构获得其实现的方式ToString。它是从结构的基类继承的。
所有可继承成员?当然不是。私人成员可遗传吗?
是。基类的所有私有成员也是派生类型的成员。如果呼叫站点不在该成员的 可访问域中 , 则按 名称呼叫这些成员当然是非法的。仅因为您拥有成员并不意味着可以使用它!
现在,我们继续原始答案:
非常好。:-)
使值类型成为值类型的原因是它的实例是 按value复制的 。使引用类型成为引用类型的原因是其实例是 通过引用复制的 。您似乎有一种信念,认为值类型和引用类型之间的 继承 关系在某种程度上是特殊且不寻常的,但是我不理解这种信念是什么。 继承与事物的复制方式无关。
这样看。假设我告诉您以下事实:
有两种盒子,红色盒子和蓝色盒子。
每个红色框都是空的。
有三个特殊的蓝色框,分别称为O,V和E。
O不在任何盒子内。
V在O内部。
E在V内部。
V内没有其他蓝框。
E内没有蓝框。
每个红色框位于V或E中。
除O以外的每个蓝框本身都位于一个蓝框内。
蓝色框是引用类型,红色框是值类型,O是System.Object,V是System.ValueType,E是System.Enum,“内部”关系是“派生自”。
如果您有很多硬纸皮和很多耐心,那是一套完全一致和直接的规则,可以轻松实现自己的规则。一个盒子是红色还是蓝色与里面的东西无关。在现实世界中,完全有可能在蓝色框内放置一个红色框。在CLR中,使值类型继承自引用类型是完全合法的,只要它是System.ValueType或System.Enum。
因此,让我们改写您的问题:
ValueTypes如何从Object(ReferenceType)派生而仍然是ValueTypes?
如
每个红色框(值类型)如何可能在框O(System.Object)的内部(派生自该框)(是蓝色框(引用类型),而仍然是红色框(值类型))?
当您这样说时,希望它是显而易见的。没有什么可以阻止您在框V内放置一个红色框,该框位于框O内,该框为蓝色。为什么会有?
附加更新:
琼最初的问题是关于如何 可能的 值类型是从引用类型派生的。我最初的回答并没有真正解释CLR用来解释以下事实的任何机制:我们在具有完全不同表示形式的两件事之间具有派生关系,即所引用的数据是否具有对象标头,同步块,是否出于垃圾回收目的拥有自己的存储空间,等等。这些机制很复杂,太复杂了,无法一口气解释。CLR类型系统的规则比我们在C#中看到的稍微简化的样式要复杂得多,例如,在框式和未框式的类型之间没有明显的区别。泛型的引入还导致将许多其他复杂性添加到CLR。