2012-03-23 77 views
5

我知道我的问题似乎愚蠢,但我很困惑。我很感激,如果有人为我澄清这一点。System.Object类和Structs之间的关系

我知道结构,例如Int32是值类型,并在堆栈上实例化,而类是引用类型并在堆上实例化。我也知道所有的结构都来自System.Object类型,这是一个类。我想知道超类型System.Object是一个引用类型并且子类型Int32是一个值类型吗?我应该在哪里看明白这是如何工作的?

+7

相关阅读:[堆栈是一个实现细节(http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation -detail.aspx) – Heinzi 2012-03-23 07:29:50

+2

可能的重复http://stackoverflow.com/questions/1682231/how-do-valuetypes-derive-from-object-referencetype-and-still-be-valuetypes – daryal 2012-03-23 07:37:00

+0

这是编译器已知的 – 2012-03-23 07:53:12

回答

11

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

你不知道,因为为了被列为知识一个信念,一定要真实。这种信念当然不是真的,尽管很多人都相信它。

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

什么决定了存储在堆上分配,什么在栈上分配是已知寿命要求的存储,而不是它是什么样的东西。如果一个变量被认为是短命的,那么它可以被分配到堆栈上;如果它不知道是短命的,那么它必须分配在堆上。

我也知道所有的结构都来自System.Object类型,它是一个类。我想知道超类型System.Object是一个引用类型并且子类型Int32是一个值类型吗?

我怀疑,如果这让你感到困惑,你不明白“继承自”的意思。当我们说System.Int32是一个值类型,继承自System.Object,一个引用类型时,我们的意思是Object的所有成员也是Int32的成员。对象有一个方法“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

+5

我不是OP,但我认为继承的共同信念是像这样:如果你创建了一个Derived类型的对象,你必须(在概念上)创建一个类型为“Base”的对象,然后用每个派生类型“附加”对象,直到你构造了“Derived” (毕竟,我们正在调用链中的每个基础构造函数)。因此,为了创建一个'Int32',你必须创建一个'Object'并因此创建一个引用类型。 – 2012-03-23 16:37:24

+0

谢谢埃里克。我的想法完全像迈克尔所说的那样,对我来说也是一种奇怪的感觉。 – Morteza 2012-03-23 21:01:40

+3

@MichaelStum:关键词有“概念上” - 实际上,从概念上讲,int *的构造是一个对象的第一个构造。但是*在实践中*这不是*实际*发生的事情,因为系统已经仔细设置,所以它不需要*发生。 – 2012-03-23 22:46:42

2

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

是的,结构来自ValueTypeValueType源自Object。所以,最终的结构也衍生自Object。 (例如,该方法ToString()==Equals()GetHashCode()或许还有其他一些在Object定义并因此也可以在结构体的)

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

Eric Lippert的博客是关于C#你应该阅读@Heinzi提供的链接进一步澄清。