C#不允许 struct 从类派生,但所有值类型都从对象派生.这种区别是从哪里来的?

CLR是如何处理这一问题的?

推荐答案

C#不允许从类派生 struct

你的陈述不正确,因此你感到困惑.C#does允许从类派生 struct .所有 struct 都来自同一个类System.ValueType,它派生自系统.对象所有枚举都源于系统.枚举.

更新:在一些(现已删除) comments 中出现了一些混乱,需要澄清.我会问一些额外的问题:

struct 是否派生自基类型?

显然是的.我们可以通过阅读规范的第一页来了解这一点:

所有C#类型,包括int和double等基本类型,都从一个根对象类型继承.

现在,我注意到规范夸大了这种情况.指针类型不是从对象派生的,接口类型和类型参数类型的派生关系比此草图所示的更复杂.然而,很明显,所有 struct 类型都是从基类型派生的.

我们是否有其他方式知道 struct 类型派生自基类型?

当然 struct 类型可以覆盖ToString.如果不是其基类型的虚拟方法,它将重写什么?因此它必须有一个基类型.这个基类型是一个类.

我可以从我 Select 的类中派生一个用户定义的 struct 吗?

显然是This does not imply that structs do not derive from a cl像s号. struct 派生自类,从而继承该类的可继承成员.事实上,从特定类派生 struct 需要required:从Enum派生需要枚举,从ValueType派生 struct 需要.因为它们是required,所以C#语言forbids可以防止您在代码中声明派生关系.

为什么要禁止呢?

当一段关系为required时,语言设计者有选项:(1)要求用户输入所需的咒语,(2)使其可选,或(3)禁止.每种语言都有优缺点,C语言设计师根据每种语言的具体细节做出了不同的 Select .

例如,常量字段必须是静态的,但禁止说它们是静态的,因为这样做首先是毫无意义的废话,其次意味着存在非静态常量字段.但是重载的操作符需要被标记为静态的,即使开发者别无 Select ;开发人员很容易相信操作符重载是一种实例方法.这压倒了用户可能会相信"静态"意味着,比如说"虚拟"也是一种可能性的担忧.

在这种情况下,要求用户说他们的 struct 派生自ValueType似乎仅仅是多余的言辞,这意味着 struct could派生自另一种类型.为了消除这两个问题,C#使illegal在代码中声明 struct 派生自基类型,尽管它显然是这样做的.

类似地,所有委托类型都源自Multic像tDelegate,但C#要求您说出not.

所以,现在我们已经确定了all structs in C# derive from a cl像s个.

inheritancederivation from a cl像s之间的关系是什么?

许多人对C#中的继承关系感到困惑.继承关系非常简单:如果 struct 、类或委托类型D派生自类类型B,那么B的可继承成员也是D的成员.就这么简单.

当我们说 struct 派生自ValueType时,关于继承意味着什么?简单地说,ValueType的所有可继承成员也是该 struct 的成员.例如,这就是 struct 获得ToString的实现的方式;它是从 struct 的基类继承而来的.

所有可遗传成员?当然不是.私有成员是可遗传的吗?

对基类的所有私有成员也是派生类型的成员.当然,如果通话地点不在该会员的accessibility domain个电话号码内,那么用名字称呼这些会员是违法的.仅仅因为你有会员并不意味着你可以使用它!

我们现在继续回答原来的答案:


CLR如何处理这个问题?

非常好.:-)

值类型之所以成为值类型,是因为它的实例是copied by value.引用类型之所以成为引用类型,是因为它的实例是copied by reference.您似乎认为值类型和引用类型之间的inheritance关系在某种程度上是特殊和不寻常的,但我不明白这种信念是什么.Inheritance h像 nothing to do with how things are copied.

这样看.假设我告诉你以下事实:

  • 有两种盒子,红色的

  • 每个红色的盒子都是空的.

  • 有三个特殊的蓝色盒子叫做O、V和E.

  • O不在任何盒子里.

  • V在O里面.

  • E在V里面.

  • V内没有其他蓝色盒子.

  • E里面没有蓝色的盒子.

  • 每个红色方框都在V或E中.

  • 除了O以外的每个蓝色盒子本身都在一个蓝色盒子里.

蓝框是引用类型,红框是值类型,O是System.Object,V是System.ValueType,E是System.Enum,"Inside"关系是"派生自".

这是一套完全一致且直截了当的规则,如果你有很多硬纸板和耐心的话,你可以很容易地自己实施.盒子是红色还是蓝色与里面的东西无关;在现实世界中,把一个红色的盒子放在一个蓝色的盒子里是完全可能的.在CLR中,创建从引用类型继承的值类型是完全合法的,只要它是系统中的任何一个.值类型或系统.枚举.

所以让我们重新表述你的问题:

ValueTypes如何从Object(ReferenceType)派生而来,并且仍然是ValueTypes?

为什么每个红框(值类型)都在框O(System.Object)内(派生自),它是蓝框(引用类型),但仍然是红框(值类型)?

When you phr像e it like that, I hope it's obvious. There's nothing stopping you from putting a red box inside box V, which is inside box O, which is blue. Why would there be?


另一个更新:

Joan's original question w像 about how it is possible that a value type derives from a reference type. My original answer did not really explain any of the mechanisms that the CLR uses to account for the fact that we have a derivation relationship between two things that have completely different representations -- namely, whether the referred-to data h像 an object header, a sync block, whether it owns its own storage for the purposes of garbage collection, and so on. These mechanisms are complicated, too complicated to explain in one answer. The rules of the CLR type system are quite a bit more complex than the somewhat simplified flavour of it that we see in C#, where there is not a strong distinction made between the boxed and unboxed versions of a type, for example. The introduction of generics also caused a great deal of additional complexity to be added to the CLR. Consult the CLI specification for details, paying particular attention to the rules for boxing and constrained virtual calls.

.net相关问答推荐

使用PowerShell在Windows容器内安装exe

无法在Ubuntu 22.04.3上运行带有Rider 2023和DotNet-8.0的项目

竖线在 PropertyGroup .csproj 文件中的含义

C#/.NET + VisualStudio,命名空间问题

在 WP7 中将 List 转换为 ObservableCollection

为什么 .NET 中的 System.Version 定义为 Major.Minor.Build.Revision?

调整小数精度,.net

在 ASP.NET MVC 中我可以在哪里放置自定义类?

根源是什么?

发布版本中的 Debug.WriteLine

在 WinForms 应用程序中查找焦点控件的首选方法是什么?

使用 Task.Factory.StartNew 传递方法参数

找不到 Microsoft.Office.Interop Visual Studio

.net 服务总线建议?

Convert.ToBoolean 和 Boolean.Parse 不接受 0 和 1

Linq to SQL - 返回前 n 行

.NET 配置文件 configSource 在应用程序目录文件夹之外

自创建数据库以来,支持ApplicationDbContext上下文的模型已更改

将 Dictionary 转换为匿名对象?

是 C# 中的 bool 读/写原子