ValueTypes 如何从 Object (ReferenceType) 派生并仍然是 ValueTypes? [英] How do ValueTypes derive from Object (ReferenceType) and still be ValueTypes?

查看:29
本文介绍了ValueTypes 如何从 Object (ReferenceType) 派生并仍然是 ValueTypes?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C# 不允许结构派生自类,但所有 ValueType 派生自 Object.这种区别在哪里?

C# doesn't allow structs to derive from classes, but all ValueTypes derive from Object. Where is this distinction made?

CLR 如何处理这个问题?

How does the CLR handle this?

推荐答案

C# 不允许从类派生结构体

C# doesn't allow structs to derive from classes

您的陈述不正确,因此您感到困惑.C#确实允许从类派生结构.所有结构都派生自同一个类 System.ValueType,后者派生自 System.Object.并且所有枚举都源自 System.Enum.

Your statement is incorrect, hence your confusion. C# does allow structs to derive from classes. All structs derive from the same class, System.ValueType, which derives from System.Object. And all enums derive from System.Enum.

更新:某些(现已删除)评论中存在一些混淆,需要澄清.我会问一些额外的问题:

UPDATE: There has been some confusion in some (now deleted) comments, which warrants clarification. I'll ask some additional questions:

结构是否从基类型派生?

Do structs derive from a base type?

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

Plainly yes. We can see this by reading the first page of the specification:

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

All C# types, including primitive types such as int and double, inherit from a single root object type.

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

Now, I note that the specification overstates the case here. Pointer types do not derive from object, and the derivation relationship for interface types and type parameter types is more complex than this sketch indicates. However, plainly it is the case that all struct types derive from a base type.

还有其他方法可以让我们知道结构类型是从基类型派生的吗?

Are there other ways that we know that struct types derive from a base type?

当然.结构类型可以覆盖 ToString.如果不是其基类型的虚方法,它覆盖的是什么?因此它必须有一个基本类型.该基类型是一个类.

Sure. A struct type can override ToString. What is it overriding, if not a virtual method of its base type? Therefore it must have a base type. That base type is a class.

我可以从我选择的类派生一个用户定义的结构吗?

May I derive a user-defined struct from a class of my choice?

显然没有.这并不意味着结构不是从类派生的.结构派生自一个类,从而继承该类的可遗传成员.事实上,结构需要从特定的类派生:枚举需要从Enum派生,结构需要从ValueType派生.因为这些是必需的,C# 语言禁止您在代码中说明派生关系.

Plainly no. This does not imply that structs do not derive from a class. Structs derive from a class, and thereby inherit the heritable members of that class. In fact, structs are required to derive from a specific class: Enums are required to derive from Enum, structs are required to derive from ValueType. Because these are required, the C# language forbids you from stating the derivation relationship in code.

为什么要禁止?

当一个关系需要时,语言设计者有以下选择:(1) 要求用户输入所需的咒语,(2) 使其成为可选,或 (3) 禁止它.每个都有优点和缺点,C# 语言设计者根据每个的具体细节进行了不同的选择.

When a relationship is required, the language designer has options: (1) require the user to type the required incantation, (2) make it optional, or (3) forbid it. Each has pros and cons, and the C# language designers have chosen differently depending on the specific details of each.

例如,const 字段必须是静态的,但禁止说它们是静态的,因为这样做首先是无意义的措辞,其次,暗示存在非静态的 const 字段.但是,即使开发人员别无选择,也需要将重载运算符标记为静态;否则,开发人员很容易相信运算符重载是实例方法.这超越了用户可能会相信静态"意味着,比如说虚拟"也是一种可能性的担忧.

For example, const fields are required to be static, but it is forbidden to say that they are because doing so is first, pointless verbiage, and second, implies that there are non-static const fields. But overloaded operators are required to be marked as static, even though the developer has no choice; it is too easy for developers to believe that an operator overload is an instance method otherwise. This overrides the concern that a user may come to believe that the "static" implies that, say "virtual" is also a possibility.

在这种情况下,要求用户说他们的结构派生自 ValueType 似乎只是多余的措辞,这意味着结构 可以 派生自另一种类型.为了消除这两个问题,C# 使得在代码中声明结构派生自基类型是非法,尽管很明显它确实如此.

In this case, requiring a user to say that their struct derives from ValueType seems like mere excess verbiage, and it implies that the struct could derive from another type. To eliminate both these problems, C# makes it illegal to state in the code that a struct derives from a base type, though plainly it does.

类似地,所有委托类型都源自 MulticastDelegate,但 C# 要求您不要这么说.

Similarly all delegate types derive from MulticastDelegate, but C# requires you to not say that.

所以,现在我们已经确定C# 中的所有结构都派生自一个类.

So, now we have established that all structs in C# derive from a class.

继承从类派生有什么关系?

很多人被C#中的继承关系搞糊涂了.继承关系非常简单:如果一个结构、类或委托类型 D 派生自一个类类型 B,那么 B 的可继承成员也是 D 的成员.就这么简单.

Many people are confused by the inheritance relationship in C#. The inheritance relationship is quite straightforward: if a struct, class or delegate type D derives from a class type B then the heritable members of B are also members of D. It's as simple as that.

当我们说结构派生自 ValueType 时,继承是什么意思?简单地说,ValueType 的所有可遗传成员也是结构的成员.例如,这就是结构体如何获得它们对 ToString 的实现;它是从结构的基类继承的.

What does it mean with regards to inheritance when we say that a struct derives from ValueType? Simply that all the heritable members of ValueType are also members of the struct. This is how structs obtain their implementation of ToString, for example; it is inherited from the base class of the struct.

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

All heritable members? Surely not. Are private members heritable?

是的.基类的所有私有成员也是派生类型的成员.如果呼叫站点不在成员的可访问域中,那么按名称呼叫这些成员当然是非法的.拥有会员不代表可以使用!

Yes. All private members of a base class are also members of the derived type. It is illegal to call those members by name of course if the call site is not in the accessibility domain of the member. Just because you have a member does not mean you can use it!

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

We now continue with the original answer:

CLR 如何处理这个问题?

How does the CLR handle this?

非常好.:-)

使值类型成为值类型的原因在于它的实例按值复制.使引用类型成为引用类型的原因在于它的实例通过引用复制.您似乎相信值类型和引用类型之间的继承关系在某种程度上是特殊和不寻常的,但我不明白这种信念是什么.继承与复制事物的方式无关.

What makes a value type a value type is that its instances are copied by value. What makes a reference type a reference type is that its instances are copied by reference. You seem to have some belief that the inheritance relationship between value types and reference types is somehow special and unusual, but I don't understand what that belief is. Inheritance has nothing to do with how things are copied.

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

Look at it this way. Suppose I told you the following facts:

  • 盒子有两种,红色框和蓝框.

  • There are two kinds of boxes, red boxes and blue boxes.

每个红框都是空的.

有三个特殊的蓝色框,分别称为 O、V 和 E.

There are three special blue boxes called O, V and E.

O 不在任何盒子里.

V 在 O 里面.

E 在 V 里面.

V 内没有其他蓝色框.

No other blue box is inside V.

E 内没有蓝色框.

每个红框都在 V 或 E 中.

Every red box is in either V or E.

除 O 之外的每个蓝色框本身都在一个蓝色框内.

Every blue box other than O is itself inside a blue box.

蓝色框为引用类型,红色框为值类型,O为System.Object,V为System.ValueType,E为System.Enum,内部"关系为派生自".

The blue boxes are reference types, the red boxes are value types, O is System.Object, V is System.ValueType, E is System.Enum, and the "inside" relationship is "derives from".

这是一套完全一致且直接的规则,如果您有大量的纸板和耐心,您可以轻松地自己实施.一个盒子是红色还是蓝色与里面的东西无关;在现实世界中,将红色盒子放入蓝色盒子中是完全可能的.在 CLR 中,创建从引用类型继承的值类型是完全合法的,只要它是 System.ValueType 或 System.Enum.

That's a perfectly consistent and straightforward set of rules which you could easily implement yourself, if you had a lot of cardboard and a lot of patience. Whether a box is red or blue has nothing to do with what it's inside; in the real world it is perfectly possible to put a red box inside a blue box. In the CLR, it is perfectly legal to make a value type that inherits from a reference type, so long as it is either System.ValueType or System.Enum.

那么让我们重新表述您的问题:

So let's rephrase your question:

ValueTypes 如何从 Object (ReferenceType) 派生并仍然是 ValueTypes?

How do ValueTypes derive from Object (ReferenceType) and still be ValueTypes?

作为

怎么可能每个红框(值类型)都在(派生自)框O(System.Object)里面,它是一个蓝框(一个引用类型)并且仍然是一个红框(一个值类型)?

How is it possible that every red box (value types) is inside (derives from) box O (System.Object), which is a blue box (a reference Type) and still be a red box (a value type)?

当你这样说时,我希望它是显而易见的.没有什么能阻止你在盒子 V 里面放一个红色的盒子,盒子在盒子 O 里面,盒子是蓝色的.为什么会有?

When you phrase 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 最初的问题是关于值类型如何从引用类型派生可能.我最初的回答并没有真正解释 CLR 用来解释以下事实的任何机制,即我们在具有完全不同表示形式的两个事物之间存在派生关系——即,所引用的数据是否具有对象头、同步块,它是否拥有自己的用于垃圾收集的存储,等等.这些机制很复杂,太复杂了,无法在一个答案中解释.CLR 类型系统的规则比我们在 C# 中看到的稍微简化的风格复杂得多,例如,在 C# 中,类型的装箱和未装箱版本之间没有明显区别.泛型的引入也给 CLR 添加了大量额外的复杂性.有关详细信息,请参阅 CLI 规范,尤其要注意装箱和受限虚拟调用的规则.

Joan's original question was 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 has 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.

这篇关于ValueTypes 如何从 Object (ReferenceType) 派生并仍然是 ValueTypes?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆