我知道我的問題似乎愚蠢,但我很困惑。我很感激,如果有人爲我澄清這一點。System.Object類和Structs之間的關係
我知道結構,例如Int32是值類型,並在堆棧上實例化,而類是引用類型並在堆上實例化。我也知道所有的結構都來自System.Object類型,這是一個類。我想知道超類型System.Object是一個引用類型並且子類型Int32是一個值類型嗎?我應該在哪裏看明白這是如何工作的?
我知道我的問題似乎愚蠢,但我很困惑。我很感激,如果有人爲我澄清這一點。System.Object類和Structs之間的關係
我知道結構,例如Int32是值類型,並在堆棧上實例化,而類是引用類型並在堆上實例化。我也知道所有的結構都來自System.Object類型,這是一個類。我想知道超類型System.Object是一個引用類型並且子類型Int32是一個值類型嗎?我應該在哪裏看明白這是如何工作的?
我知道結構例如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/2010/09/30/the-truth-about-value-types.aspx
http://ericlippert.com/2011/09/19/inheritance-and-representation/
和額外的獎金,這其中也可能對你有幫助:
我不是OP,但我認爲繼承的共同信念是像這樣:如果你創建了一個Derived類型的對象,你必須(在概念上)創建一個類型爲「Base」的對象,然後用每個派生類型「附加」對象,直到你構造了「Derived」 (畢竟,我們正在調用鏈中的每個基礎構造函數)。因此,爲了創建一個'Int32',你必須創建一個'Object'並因此創建一個引用類型。 – 2012-03-23 16:37:24
謝謝埃裏克。我的想法完全像邁克爾所說的那樣,對我來說也是一種奇怪的感覺。 – Morteza 2012-03-23 21:01:40
@MichaelStum:關鍵詞有「概念上」 - 實際上,從概念上講,int *的構造是一個對象的第一個構造。但是*在實踐中*這不是*實際*發生的事情,因爲系統已經仔細設置,所以它不需要*發生。 – 2012-03-23 22:46:42
首先,值類型的區別特徵不在於它們的存儲位置,而在於它們如何傳遞給方法。 Struct的值是按值傳遞的;這是參數的副本被創建並傳遞。對方法中副本的任何更改都不會影響實際參數(除非它們共享相同的引用)引用類型通過引用傳遞;那是通過實際參數的指針。
是的,結構來自ValueType
。 ValueType
源自Object
。所以,最終的結構也衍生自Object
。 (例如,該方法ToString()
,==
,Equals()
,GetHashCode()
或許還有其他一些在Object
定義並因此也可以在結構體的)
然而,參數傳遞的語義類中沒有定義自己;在Object
的定義中沒有代碼表示「我的子類型的任何實例都要通過引用傳遞」,並且ValueType
的定義中沒有代碼表示「我的子類型的任何實例都要通過值傳遞」。 [也許有一個特殊的屬性,但不計算]這是編譯器的責任。 (在C#編譯器的某處有一些代碼表示「生成代碼,以便值類型的後代將按值傳遞,而其他代碼將通過引用傳遞」)
Eric Lippert的博客是關於C#你應該閱讀@Heinzi提供的鏈接進一步澄清。
相關閱讀:[堆棧是一個實現細節(http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation -detail.aspx) – Heinzi 2012-03-23 07:29:50
可能的重複http://stackoverflow.com/questions/1682231/how-do-valuetypes-derive-from-object-referencetype-and-still-be-valuetypes – daryal 2012-03-23 07:37:00
這是編譯器已知的 – 2012-03-23 07:53:12