【问题标题】:What makes ValueType class Special?是什么让 ValueType 类特别?
【发布时间】:2014-01-19 05:58:09
【问题描述】:

当我试图定义一个继承自 System.ValueTypeSystem.Enum 类的类时,我收到了一个错误:

Cannot derive from special class System.ValueType

我理解这个错误,但我不明白是什么让ValueType特殊?我的意思是没有关键字(如sealed)或属性来指定这个类不能被继承。ValueType 有两个属性,SerializableComVisible,但它们都与这种情况无关。@ 987654321@ 说:

虽然 ValueType 是值类型的隐式基类,您不能创建直接从 ValueType 继承的类。 相反,各个编译器会提供语言关键字或构造(例如 C# 中的 struct 和 Structure ...结束 Visual Basic 中的结构)以支持创建值类型。

但它没有回答我的问题。所以我的问题是在这种情况下如何通知编译器?当我尝试创建继承自一个类的类时,编译器是否直接检查该类是ValueType 还是Enum

编辑:所有结构 implicitly 都继承自 ValueType,但 Enum显式 继承自 ValueType,那么它是如何工作的?编译器是怎么判断出这种情况的,这些都是编译器硬编码的?

【问题讨论】:

  • 是的,我希望像这样的规则(同样适用于Delegate)在编译器代码中被硬编码,只是为了匹配语言规范。
  • 是的,它可能是正确的。但据我所知,在这些情况下使用属性和预处理器指令来通知编译器。创建一个属性来指定这个类不是更合适吗?是特殊的,不能被继承而不是硬编码?
  • @Selman22 - 根据我以前从 C# 团队的主要成员那里看到的关于 SO 的答案,听起来好像这些整数类型的绑定是硬编码到编译器中的。继承层次结构是 C# 语言设计的一个组成部分,使用属性或其他方式来描述基继承类型关系是违反直觉的。
  • @M.Babcock 我明白你的意思。我在等也许有人能清楚地解释这个原因。我也想知道 Enum 类是从 ValueType 继承的,编译器是否也硬编码?

标签: c# inheritance compiler-errors


【解决方案1】:

我理解这个错误,但我不明白是什么让 ValueType 类特别?

该类被记录为特殊的。这就是它的特别之处。

在这种情况下如何通知编译器?

编译器编写者在编写编译器之前阅读文档。

当我尝试创建继承自一个类的类时,编译器是否直接检查该类是ValueType还是Enum?

是的。

所有结构都隐式继承自 ValueType,但 Enum 类显式继承自 ValueType,那么它是如何工作的?

效果很好。

是否所有这些特殊情况都被硬编码到编译器中?

是的。

创建一个属性来指定这个类是特殊的,不能被继承而不是硬编码不是更合适吗?

不,不是。这意味着第三方也可以创建一个特殊类型,在继承时需要编译器进行特殊处理。然后第三方将如何修改编译器以实现这些规则?

【讨论】:

  • 感谢您的回答,我现在明白了。我认为文档是根据编译器编写的,但显然不是。 :)
  • @EricLippert 这浮现在脑海中,你说:That would imply that a third party could also make a special type that needed special handling by the compiler when inherited from. 但是如果你定义一个 internal attiribute 并在 ValueType 中使用它会发生什么?其他人不能使用该属性,因为它是内部的?
  • @Selman22:内部类型是实现细节。为什么要关心编译器的实现细节是什么?为什么发明一个新属性并确保该属性位于四种特殊类型(ValueType、Enum、Delegate 和 MulticastDelegate)上比简单地拥有一个包含“ValueType、Enum、Delegate、MulticastDelegate”字样的列表更容易?跨度>
  • @EricLippert,我不关心好奇心
  • @Selman22:框架设计指南是关于一组类的公共表面区域,而不是它的实现细节。
【解决方案2】:

微软并未公布其 C# 编译器源代码,因此我们只能猜测该检查是嵌入在编译器级别的。

Mono 的 C# 编译器在编译时执行这种检查,您可以在 Class.ResolveBaseTypes 方法的第 2790 行附近看到,

https://github.com/mono/mono/blob/master/mcs/mcs/class.cs

【讨论】:

  • 好点,你说得对。c# 编译器中应该有这样的代码。
【解决方案3】:

System.ValueType 是编译器的特殊处理类,用于注释值类型。编译器使用它的方式不同,因为值类型对象的处理方式与引用类型对象不同。我想this series of blog posts 可以澄清一下值和引用类型之间的差异。 This MSDN post describes the common cases of value reference types 这样您就可以轻松地对每种类型进行分类。

您的问题的答案在 .NET Common Type System 中。 如果你想创建自己的值类型类,我建议创建一个结构。复制自(Common TYPE System, Structures reference](http://msdn.microsoft.com/en-us/library/zcx1eb1e%28v=vs.110%29.aspx#Structures):

结构是隐式派生自System.ValueType 的值类型,而System.ValueType 又派生自System.Object。 ... 在 .NET Framework 类库中,所有原始数据类型(BooleanByte, Char、DateTimeDecimalDoubleInt16Int32Int64、@ 987654336@、SingleUInt16UInt32UInt64) 被定义为结构体。

与类一样,结构定义了数据(结构的字段)和可以对该数据执行的操作(结构的方法)。 ...

值类型在几个方面也与类不同。首先,虽然它们隐式继承自System.ValueType,但它们不能直接继承自任何类型。同样,所有值类型都是密封的,这意味着不能从它们派生出其他类型。 ...

对于每个值类型,公共语言运行时都提供一个对应的盒装类型,这是一个与值类型具有相同状态和行为的类。 ... 定义值类型时,您同时定义了装箱和未装箱类型

希望我能帮上忙!

【讨论】:

  • 谢谢,不是完全回答我的问题,而是很好的参考 :) 我真的想知道 特殊处理过程的执行情况。我会再次阅读这些博客文章,谢谢.
  • 我知道。我只是没有必要的见解。如果您找到了,请在此处发布。
猜你喜欢
  • 2019-11-06
  • 2011-11-22
  • 2010-12-04
  • 1970-01-01
  • 1970-01-01
  • 2011-07-03
  • 2023-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多