System.Object类与Structs之间的关系

时间:2012-03-23 07:23:20

标签: c# clr

我知道我的问题似乎很愚蠢,但我很困惑。如果有人为我澄清这一点,我感激不尽。

我知道结构,例如Int32是值类型,在堆栈上实例化,而类是引用类型,并在堆上实例化。我也知道所有结构都是从System.Object类型派生的,这是一个类。我想知道超类型System.Object是一个引用类型,而子类型Int32是一个值类型是怎么可能的?我应该在哪里了解它是如何工作的?

2 个答案:

答案 0 :(得分:11)

  

我知道结构,例如Int32是值类型,在堆栈上实例化,而类是引用类型,并在堆上实例化。

你不知道,因为为了被归类为知识,信仰必须是 true 。虽然很多人都相信,但这种信念当然不是真的。

值类型有时在堆栈上分配。 引用有时在堆栈上分配,引用堆上分配的内存。值类型有时在堆上分配。 (当然,值类型和引用也可以在寄存器中分配,既不是堆栈也不是堆。)

什么决定了在堆上分配的存储以及在堆栈上分配的内容是存储的已知生存期要求,而不是它是什么类型的。如果已知变量是短暂的,那么它可以在堆栈上分配;如果不知道它是短暂的,那么它必须在堆上分配。

  

我也知道所有结构都是从System.Object类型派生的,这是一个类。我想知道超类型System.Object是一个引用类型,而子类型Int32是一个值类型是怎么可能的?

如果这让你感到困惑,我怀疑你不明白“继承”是什么意思。当我们说System.Int32(一个值类型)继承自System.Object(一个引用类型)时,我们的意思是 Object的所有成员也是Int32 的成员。 Object有一个方法“ToString”。那是Object的成员。因此Int32也有一个方法“ToString”,因为Int32继承自Object。

继承意味着所有。我怀疑你相信继承意味着别的东西,而且无论那个“东西”是什么都会阻止值类型扩展引用类型。无论你有什么信念让你认为价值类型不能从引用类型继承,显然是错误的,因为很明显它们确实存在。

我有兴趣了解人们对编程语言的错误认识;您认为不正确的继承关系是什么,会阻止值类型从引用类型派生?

您应该阅读并理解所有这些文章:

http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

http://blogs.msdn.com/b/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx

http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

http://ericlippert.com/2011/09/19/inheritance-and-representation/

额外的奖励,这个也可能对你有所帮助:

http://blogs.msdn.com/b/ericlippert/archive/2012/01/16/what-is-the-defining-characteristic-of-a-local-variable.aspx

答案 1 :(得分:2)

首先,值类型的区别特征不是它们存储的位置,而是它们如何传递给方法。结构是按值传递的;这是参数的副本被创建并传递。方法中对副本的任何更改都不会影响实际参数(除非它们共享相同的引用)引用类型通过引用传递;传递的是指向实际参数的指针。

是的,结构派生于ValueTypeValueType源自Object。因此,最终结构也来自Object。 (例如,方法ToString()==Equals()GetHashCode()以及其他一些方法在Object中定义,因此也可以在struct中使用)< / p>

但是,参数传递的语义不是在类本身中定义的; Object的定义中没有代码表示“我的子类型的任何实例都将通过引用传递”,并且ValueType的定义中没有代码表示“我的子类型的任何实例”要通过价值“。 [也许有一个特殊属性,但不计算在内]编译器有责任尊重这一点。 (C#编译器中的某些代码表示“生成代码使得ValueType的后代将按值传递,而其他代码将通过引用传递”)

Eric Lippert的博客是关于C#的许多问题的绝佳资源,您应该阅读@Heinzi提供的链接以进一步澄清。