2010-05-20 126 views
1

1)什麼是int?它與structSystem.Int32有什麼不同?我知道前者是CLR類型System.Int32的C#別名(typedef#define當量)。這種理解是否正確?幾個C#語言問題

2)當我們說:

IComparable x = 10; 

是,像他說:

IComparable x = new System.Int32(); 

但我們不能new一個結構,對不對?

或用C等的語法:

struct System.In32 *x; 
x=>someThing = 10; 

3)什麼是String大寫小號?我在Reflector中看到它是sealedString類,它當然是一個引用類型,與上面的System.Int32不同,它是一個值類型。

什麼是string,但沒有資金的s,但?那也是這個類的C#別名嗎?

爲什麼我在Reflector中看不到別名定義?

4)如果你願意的話,試着跟隨我這個微妙的思路。我們知道特定類型的存儲位置只能訪問其接口上的屬性和成員。這意味着:

Person p = new Customer(); 
p.Name = "Water Cooler v2"; // legal because as Name is defined on Person. 

// illegal without an explicit cast even though the backing 
// store is a Customer, the storage location is of type 
// Person, which doesn't support the member/method being 
// accessed/called. 
p.GetTotalValueOfOrdersMade(); 

現在,與推論,考慮此方案:

int i = 10; 

// obvious System.object defines no member to 
// store an integer value or any other value in. 
// So, my question really is, when the integer is 
// boxed, what is the *type* it is actually boxed to. 
// In other words, what is the type that forms the 
// backing store on the heap, for this operation? 
object x = i; 

更新

謝謝您的回答,埃裏克Gunnerson和Aaronought。恐怕我沒有足夠清晰地表達我的問題以吸引非常滿意的答案。麻煩的是,我從表面上知道我的問題的答案,而且我決不是一個新手程序員。

但我不得不承認,只要我是一名程序員,即使我編寫了正確的代碼,但對於語言及其底層平臺/運行時處理類型存儲的複雜性的深入理解, 。

+5

請不要在同一個問題提交多個不相關的問題。 – 2010-05-20 23:29:32

+0

「我們不能新建一個結構體」:是的,我們可以......爲什麼我們不能? – 2010-05-21 00:51:16

回答

1

1)是的。 「int」只是C#爲System.Int32定義的別名。

2)您的第一個答案。

3)字符串是System.String類型的C#別名。由於幾乎每個人都有「使用系統」在他們的程序中,您可以使用「字符串」或「字符串」。

4)您可以將其視爲存儲在引用類型框中的int。即使框的類型僅作爲「對象」可見,運行時知道其中有一個int。

這就是爲什麼你不能寫:

int i = 10; 
object x = i; 
short j = (short) x; // this is an error because you can only unbox x as an int. 

這在很大程度上是在C#語言參考或的入門書籍之一。

5
  1. intSystem.Int32的別名。類型是相同的。

  2. IComparable x = 10將類似於編寫var i = 10; IComparable x = i。編譯器選擇它認爲最可能的常量類型,然後隱式轉換爲IComparable

  3. stringSystem.String的別名,與#1類似。您無法在Reflector中看到別名定義,因爲別名是C#編譯器的一部分,而不是.NET Framework本身。 (例如,在VB.NET中有所不同)。

  4. 盒裝整數或其他值類型是對該值的引用。你可以把它想象成一個附帶一些類型信息的指針。但是,實際的支持類型只是System.Object

+0

+1好答案! – 2010-05-21 00:24:27

2

我只回答問題2和問題4,因爲看起來其他人已經得到滿意的回答了。

首先,讓我們來看看從你的問題驗證碼:

int i = 10; 
object x = i; 

現在,像你這得太多聲音給我。是的,的確,System.Object類型不包含代表int的成員,該成員已在此處裝箱。但是,這並不使這種情況下,任何不同於您發佈的其他代碼,你似乎完全理解:

Person p = new Customer(); 
p.Name = "Water Cooler v2"; 

在這種情況下,Customer類從Person類派生。有的字段,方法等在Person的上下文中不可見,但是Customer a Person。同樣,System.Int32(與其他人指出的int一樣)派生自System.Object。簡單地說,您可以在int上執行從object的上下文中不可見的操作 - 例如執行加法等。但是intobject

因此,對於「實際上放在堆上的內容是什麼?」的回答。 (順便說一下,堆是CLR的一個實現細節)其實很簡單:在那裏放置一個int

現在,如果我可以走回頭路了一下,我想對這個問題作出迴應:

但我們不能new一個結構,對不對?

其實,這是不準確的。關鍵字new做什麼?這聽起來像你在C++的角度思考,並假設如果一個類型是堆棧(再次:一個實現細節,你介意)上分配,然後使用new關鍵詞是沒有意義的。但在C#中,new基本上只意味着你正在調用該類型的構造函數。值類型(結構體)的構造函數就像引用類型(類)一樣;所以,是的,這條線:

IComparable x = 10; 

實際上是相同的:

IComparable x = new System.Int32(10); // if System.Int32 had a public 
             // parameterized constructor 
             // (which it doesn't, probably 
             // because that would just 
             // confuse people) 

現在,讓一個問題:是什麼樣的價值類型之間的重要差異.NET中的引用類型?如果你的答案涉及到任何「堆疊」,「堆」或「分配」的話,那麼你有可能把注意力集中在錯誤的事情上。對於我們來說,對於分配對象的開發人員而言(與性能調整相關的細節除外)有什麼關係?該重要區別,就我而言,僅僅是值類型是按值傳遞(複製)的方法調用。老實說,就是這樣。這是重要的。

當你這樣看,裝箱/拆箱的大奧祕是真的沒有那麼神祕。讓我們來看看這段代碼再次:​​

int i = 10; 
object x = i; 

我們說,在上面的代碼,我們是「拳擊」的對象x整數i。但這個術語「拳擊」是什麼意思?這與將值放在堆上相同嗎?如果堆與堆棧分配是未指定的實現細節,這怎麼可能?請記住我對價值類型所說的話。關於int是值類型,重要的是,只要你傳遞一個int一種方法,你真的傳遞一個副本。這是所有值類型的行爲,這與說出從System.ValueType派生的所有類型相同。但是請注意,System.ObjectSystem.ValueType派生。這是相反的方式。 object是一個參考類型。

那麼,「拳」 真的的意思是,你正在做的是,憑藉其類型的,總是按值傳遞的對象,而且它鑄造於通過引用傳遞一個基本類型(object) *。

如果我可以提供一個有點傻的比喻:假設你去哪裏了以下規則適用一些奇怪的主題公園:

  1. 所有的人都在默認情況下坐摩天輪。
  2. 紐約人,特別是騎在旋轉木馬上。

在你進入公園之前,你需要填寫一張自己分類的小表格。轉入此表單後,如果您來自紐約,則會收到紅色腕帶,否則會收到藍色腕帶。

如果你來自紐約,但你想騎摩天輪怎麼辦?很簡單:在表格上,不要填寫你的分類爲「紐約客」,你只需寫上「人」。賓果,他們給你一個藍色的腕帶,你的是,

的主要區別在這裏是做什麼之間的對象可以以及它們是如何處理。正如我多次說過的,System.Int32派生自System.Object,因此您可以將int轉換爲object,就像您可以將任何類型的對象轉換爲其派生類型的對象一樣。所有這些都會限制你能夠使用該對象執行,因爲只有基類的方法,字段等可用。沒有什麼特別的。但是通過將int改爲object,您改變了處理方式。就像在主題公園示例中將自己更改爲「人物」 - 比您確實是一個不太具體的東西,「紐約人」或換句話說基本類型 - 您更改了方式被治療。

這有道理嗎?


*指出引用類型「按引用傳遞」可以說是沒有嚴格準確的說法,並已造成了很多困惑許多開發者(更準確的說法可能是通過傳遞「引用引用類型值」);爲了徹底討論這個問題,你需要看看其他地方。

+0

感謝您的激發討論,丹。你現在正在我看到地平線的地方接壤。可悲的是,儘管如此,在我能夠恢復關於該主題的智能對話之前,我需要休息一下。黎明在我星球的一部分剛剛破裂,我已經清醒了很久。 雖然,我希望繼續討論。 – 2010-05-20 23:59:01

+0

@Water Cooler v2:我在回答中增加了很多內容,儘可能使解釋清楚。希望我不會讓這件事更加混亂。如果你有更多的問題,請看看並告訴我。 – 2010-05-21 13:51:11

0

1)int是結構System.Int32的別名。你可以在C#中定義你想要的一個類型的別名。爲此,您需要使用類似於通常用於導入名稱空間的使用統計信息的使用語句。舉例來說,如果我想創建一個別名System.Int64並調用它的號碼,我會在我的代碼文件的開頭寫上如下使用statment:

using number = System.Int64; 

然後,我每次使用時間別名號碼在我的代碼上,編譯器和intellisense會將其嚴格視爲System.Int64。

2)使用System.Int32的默認構造函數與將0賦值給整型變量相同。

IComparable x = new System.Int32(); 

確實exaclty一樣的代碼

IComparable x = 0; 

它可以使用new運算符的結構。 新的的語義分配一個對象所需的內存並調用構造函數。定義爲結構的對象與定義爲類的對象之間的區別在於它是如何分配的。 struct intances在堆棧中分配,而類實例在堆中分配。

一些有趣的事實是在C#not everything derivates from object

3)字符串是C#編譯器(作爲int關鍵字)的關鍵字,這就是爲什麼您無法使用Reflector查看其定義的原因。事實上,由編譯器生成的IL代碼現在甚至不存在這些別名的存在,因爲它們在編譯過程中僅由編譯器使用。彙編後全部字符串引用在您的編譯代碼中成爲System.String。

4)這個問題的答案是太長了,所以我建議你閱讀以下文章:Representation and Identity