System.ValueType了解

Sar*_*gam 31 c# .net-2.0

我试图创建一个ValueType.

我知道创建一个结构对我有帮助.

我还尝试从System.ValueType派生一个类型,它是一个抽象类.

但我得到一个编译器错误消息" ..无法从特殊类System.ValueType派生 "

当我看到ValueType的元数据时,它看起来是一个常规的抽象类.

  1. 是什么让它与众不同?

  2. 是C#compilor感觉它特别吗?

  3. 如果是这样,它是否建议作为编译器设计的规则?我的意思是它是公共语言规范的一部分吗?

Jon*_*nna 41

ValueType是一个小小的谎言.

内置的数字类型(int,long,byte),char,enums和structs都是值类型.

这意味着它们具有不同的身份概念和对象类型的等同性.如果我这样做x = y,x和y是引用类型,那么x和y现在指向完全相同的对象.但是,如果我这样做,x = y而x和y都是值类型,那么x和y现在是两个完全不同的对象,恰好相同.(这也反映在==Equals,虽然可以被覆盖).

(这是人们通过讨论堆栈和堆来讨论堆栈的问题,如果它们还没有,实际上这是一个实现细节,虽然重要的是,它不是值和引用类型之间的区别点).

现在,大多数情况下这一切都很好,但有关引用类型的一件事是它们都可以从继承System.Object中获益.值类型int并不是真的,这也很好,因为它在很多方面要好得多,它只是由可爱的CPU指令处理的四个字节的内存,这些指令非常擅长.尽管如此,有时候能够将int视为从System.Object继承而来也是有用的,所以你可以这样做.

当然,这意味着你可以用int做一些只对System.Object有意义的东西,所以当你这样做时,int被"装箱",然后可以再次"取消装箱".

这很好,但是如果我们想要对价值类型做一些特定的事情呢?更重要的是,如果CLR的设计者做了什么(特别是,他们想要一个GetHashCode用于与上面描述的基于值的等价相关的值类型,而不是对象具有的基于身份的等价)?

为此,我们有ValueType.系统将所有值类型视为从此类继承,而该类继承自Object.枚举依次继承自值类型,并且所有枚举类型都从它继承,允许所有枚举中的一些常用功能.

因此,如果您想要处理所有值类型的超类,请使用ValueType,但如果您想要实际创建值类型,请根据需要创建结构或枚举.


通用型系统说明:

结构是从System.ValueType隐式派生的值类型,System.ValueType又从System.Object派生.结构对于表示内存要求较小的值以及将值作为按值参数传递给具有强类型参数的方法非常有用.在.NET Framework类库中,所有基本数据类型(Boolean,Byte,Char,DateTime,Decimal,Double,Int16,Int32,Int64,SByte,Single,UInt16,UInt32和UInt64)都被定义为结构.

与类一样,结构定义数据(结构的字段)和可以对该数据执行的操作(结构的方法).这意味着您可以在结构上调用方法,包括在System.Object和System.ValueType类上定义的虚方法,以及在值类型本身上定义的任何方法.换句话说,结构可以包含字段,属性和事件,以及静态和非静态方法.您可以创建结构实例,将它们作为参数传递,将它们存储为局部变量,或将它们存储在另一个值类型或引用类型的字段中.结构也可以实现接口.

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

对于每种值类型,公共语言运行库提供相应的盒装类型,该类型具有与值类型相同的状态和行为.将值类型的实例传递给接受System.Object类型的参数的方法时,将其装箱.当控件从接受值类型作为by-reference参数的方法调用返回时,它被取消装箱(即,从类的实例转换回值类型的实例).有些语言要求在需要盒装类型时使用特殊语法; 其他人在需要时自动使用盒装类型.定义值类型时,您将同时定义盒装和未装箱类型.

ValueType的陌生感是允许上述情况发生.

  • 我感谢你的解释。但实际上,他们是如何使它如此特别仍然是我的问题。System.ValueType 不是密封和抽象的。所以它应该有资格成为父类。(对于 Enum、Int32 等也是如此)如果 C# 编译器将它特殊对待,那么它也应该在其他语言中(VB.Net、J#)。但是我在 Microsoft 公共语言规范中没有看到注释。http://msdn.microsoft.com/en-us/library/12a7a7h3.aspx。所以我仍然认为有一些隐藏的东西,这有不同的解释。 (2认同)
  • 看起来像一只鸭子,像鸭子一样呱呱叫,像鸭子一样游泳,它是一只鸭子.但事实并非如此. (2认同)

Joe*_*eau 5

无法从 ValueType 派生是 C# 编译器特有的。如果我们看一下托管 C++ 代码:

value class Foo {};
value class Foo : System::ValueType {};
Run Code Online (Sandbox Code Playgroud)

这两个都可以编译并且是相同的。当然,

ref class Foo : System::ValueType {};
Run Code Online (Sandbox Code Playgroud)

将给出错误 C3050:引用类无法从“System::ValueType”继承。
不确定其他编译器允许什么。

如果要从 C# 中的 ValueType 派生,请使用结构而不是类,编译器会处理它。