2012-07-12 18 views
64

selectedItem有兩個字段:爲什麼.ToString()在空值的可空int上工作正常時,空字符串上的.ToString()會導致null錯誤?

  • int? _cost
  • string _serialNumber

在這個例子中,_costselectedItem_serialNumber都是NULL。我讀通過的通過它們的屬性selectedItem的領域,並在文本框與他們的價值觀,當填充...

TextBox1.Text = selectedItem.Cost.ToString(); //no error 
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error 

我明白SerialNumber.ToString()是多餘的(因爲它已經是一個字符串),但我不」不懂爲什麼這導致該異常:

Nullable object must have a value.

  • int? _cost是空的,並且不具有價值,但它並沒有給我的異常。
  • string _serialNumber是可以爲空,並且沒有值,但它確實給我例外。

上呢?這question接觸,這傢伙基本上是問同樣的事情,但沒有指定的答案,也沒有解釋爲什麼一個可以爲空int?例如,我可以在可空的int上使用.ToString(),但不能在空字符串上使用?

+0

您鏈接到的問題是不一樣的。那個問題是關於'MessageBox.Show'和'String.Concat'如何使用'null'字符串。 – 2012-07-12 10:28:03

+9

請注意,您使用「可空」這個詞來表示兩個完全不同的東西。 'int?'是一個值類型,稱爲'Nullable ',它具有對空值的特殊處理; 'string'是一個引用類型,(雖然有點奇怪),它可以*實際上有* null的值。一個'int?'總是有一個值,它只是有一種特殊的方式來表示「我現在的行爲像'null'」。 – 2012-07-12 16:45:24

+0

謝謝大家的好評和澄清。很多東西都是我以前不知道的。 – CptSupermrkt 2012-07-13 01:04:52

回答

87

因爲string類型的null真的指向沒有,內存中沒有任何對象。
但是int?類型(可爲空)即使值設置爲null仍指向某個對象。
如果您閱讀Jeffrey Richter的「通過C#的CLR」,您會發現可爲空類型只是具有一些封裝邏輯的常見類型的外觀類,以便使DB null更便利。

檢查msdn瞭解可空類型。

+0

http://www.blackwasp.co.uk/ValueReferenceTypes.aspx – Tassadaque 2012-07-12 07:30:14

+7

所以基本上,因爲它不是實際上是空的,它只是假裝是? – 2012-07-12 11:56:14

+3

是的,基本上它是一個圍繞int字段和布爾符號的結構,指示此結構是否設置爲int值,或者仍然是單位化的,這表示空值。在[這個](http://stackoverflow.com/questions/2503811/how-are-nullable-types-implemented-under-the-hood-in-net)主題Mark Gravell粘貼了'Nullable '類型的實現。 – 2012-07-12 12:17:35

31

A Nullable<int>struct並且不能爲空。所以調用「null」結構的方法仍然有效。

有一些「編譯器魔術」使得_cost == null成爲一個有效的表達式。

+2

它「編譯魔術」還是運算符重載? – 2012-07-12 07:27:30

+12

@PeteBaughman:我相信編譯魔法。 – Mehrdad 2012-07-12 07:28:23

+4

這是編譯器的魔力。使用普通的C#代碼(即運算符重載)添加從'null'到'Nullable '的隱式轉換將需要您能夠從表達式'null'推斷出一種類型,這是你不能的,因爲它不會沒有一個。編譯器實質上是將'可空富= null'成'可空富=默認(可空)'和'FOO == null'成'!foo.HasValue'。 – 2012-07-12 21:30:35

2

Nullable實際上是一個暴露兩個屬性的結構:HasValue和Value。如果你這樣做,你會得到你的錯誤:

int? i = null; 
i.Value.ToString() 

爲了檢查你的int?有一個值,您可以訪問i.HasValue

+2

不是_completely_真。該代碼不會拋出'NullReferenceException',而是拋出'InvalidOperationException'。請參見[Nullable(T).Value](http://msdn.microsoft.com/zh-cn/library/ydkbatt6.aspx)。 – comecme 2012-07-12 18:52:05

14

int?實際上並不是一個對象,但它是一個Nullable<int>對象。

所以,當你聲明int? _Cost,你實際上是宣告Nullable<int> _Cost_Cost.Value屬性是undefined不是_Cost對象本身。

It is actually a syntactic sugar to use non nullable types like int , bool or decimal easily.

根據MSDN

The syntax T? is shorthand for System.Nullable<T> , where T is a value type. The two forms are interchangeable.

+0

技術上,'_Cost.Value'是未定義的時'_Cost'爲空(即,當'_Cost.HasValue'爲假) – 3Doubloons 2012-07-12 14:56:35

+3

@AlexBrault:'_Cost'不能真正'null',因爲它不是一個引用類型。 – comecme 2012-07-12 18:56:13

+0

@comecme:因此括號澄清。 – 3Doubloons 2012-07-13 00:53:59

1

什麼,我想原因是,當編譯器遇到一個原始數據類型它包裝它,它對應的對象。 toString()方法調用只是一個間接調用(包裝然後調用方法),在那裏處理異常。 雖然在String的情況下,我們直接調用該方法。當指向一個null時,該方法拋出異常。

0
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error 

yiels錯誤,因爲它調用函數ToString()這是System.String的成員。這個函數返回這個System.String的實例;沒有執行實際的轉換。另外,String是一個引用類型。引用類型包含指向保存數據的另一個內存位置的指針。

TextBox1.Text = selectedItem.Cost.ToString(); //no error 

,因爲它調用的功能ToString()這是System.Integer的成員產生任何錯誤。該函數將此實例的數值轉換爲其等效的字符串表示形式。另外,Integer是一個值類型。如果數據類型將數據保存在其自己的內存分配中,則它是一個值類型。

相同的函數名稱ToString()但執行不同的任務。

String.ToString Method

Int32.ToString Method

Value types and reference types

1

原因很簡單。 int?Nullable<int>結構value type,它不能爲空

int? _cost = null; 

_cost將有兩個字段ValueHasValue,當我們分配null_costHasValue標誌將被設置爲falseValue字段將在被分配default(T)

所以,當我們這樣做會發生什麼它的情況是int?它將0

現在,當我們在_costToStringNullable<T>ToString一個覆蓋定義,如果我們看一下Microsoft's provided Source Reference就像實現:

public override string ToString() { 
    return HasValue ? value.ToString() : ""; 
} 

因此,它返回一個空字符串,因爲_cost分配null

現在來的string _serialNumber的情況。作爲string這是一個引用類型,它可以純粹持有null。如果它持有null,那麼在其上調用ToString會產生如預期的空引用異常。

您可能會看到:Value Types and Reference Types - MSDN

相關問題