KB-Nullable Value Type: varName == null ?

.NET裡的變數型別分為Value Type(如int, bool)與Reference Type(如StringBuilder, SqlConnection),其中Value Type的資料內容直接放在堆疊(Stack)中,不像Reference Type需要Pointer指向真正的資料位置,因而Value Type的變數沒法指定為null。(延伸閱讀: 1 2)

.NET 2.0提供了Nullable Value Type,實際上是用一個泛型結構(Generic Structure)去包裝Value Type,詳細的說明請大家看官方文件,這裡就不雞婆了。我學習Nullable Type時,只看了Nullable Structure Members文件就匆匆用了起來(其實我應該先看看Using Nullable Type的),關於資料是否為null的判斷就乖乖地寫成: if (i.HasValue) { j=i.Value; }

昨天同事小娟跟我說她測試的結果,其實寫: if (i==null) { j=i; }就可以了(驚! 我當了好一陣子的笨蛋)

親手做了測試,i==null的寫法OK,j=i的寫法有個但書,就是j必須跟i一樣是Nullable Type,不然Compile時會出錯。不過,我們共同的疑問是,i==null與i.HasValue的寫法當真完全相同? 會不會在某些情境下有特殊限制?

我驗證這個問題的方法是寫了如下的Code,Build成EXE檔後,再用ILDASM反組譯。

static void TestNullable()
{
    int? i = null;
    if (i == null)
        Console.WriteLine("i == null");
    if (!i.HasValue)
        Console.WriteLine("i has value");
    int? x = i;
    int y = i.Value;
}

ILDASM反組譯的結果,可以看到i==null與i.HasValue最後會被編譯成完全相同的MSIL Code。

.method private hidebysig static void TestNullable() cil managed
{
// Code size 64 (0x40)
.maxstack 1
.locals init ([0] valuetype [mscorlib]System.Nullable`1<int32> i,
[1] valuetype [mscorlib]System.Nullable`1<int32> x,
[2] int32 y,
[3] bool CS$4$0000)
IL_0000: nop
IL_0001: ldloca.s i
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<int32>
IL_0009: ldloca.s i
IL_000b: call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
IL_0010: stloc.3
IL_0011: ldloc.3
IL_0012: brtrue.s IL_001f
IL_0014: ldstr "i == null"
IL_0019: call void [mscorlib]System.Console::WriteLine(string)
IL_001e: nop
IL_001f: ldloca.s i
IL_0021: call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brtrue.s IL_0035
IL_002a: ldstr "i has value"
IL_002f: call void [mscorlib]System.Console::WriteLine(string)
IL_0034: nop
IL_0035: ldloc.0
IL_0036: stloc.1
IL_0037: ldloca.s i
IL_0039: call instance !0 valuetype [mscorlib]System.Nullable`1<int32>::get_Value()
IL_003e: stloc.2
IL_003f: ret
} // end of method Program::TestNullable

由以上的分析來看,在C#中可以直接引用i==null,應該算是C# Compiler(CSC.EXE)的佛心來著,而我們在撰寫相關程式碼時,就大大方方享受這項貼心服務吧!

歡迎推文分享:
Published 29 May 2007 03:31 PM 由 Jeffrey
Filed under: ,
Views: 11,059



意見

# chicken said on 29 May, 2007 06:36 AM

c# compiler 藏太多 syntax candy, 常常讓你搞不清楚到底發生啥事... 不過加好還是不加好? 當然是加... :D

# I'm Ant Only said on 10 September, 2007 07:19 PM

>>Value Type的變數沒法指定為null

應該可以,不過就相當於 re-initialize value. e.g.

int i = null; '// i == 0

Nullable<T>是Structure/Value Type,只是它的Null值是

Nullable<int> Ni = null;

'// Ni.hasValue = false

'// Ni.Value = undefined (InvalidOperationException)

# Jeffrey said on 10 September, 2007 09:11 PM

To "I'm Ant Only":

int i=null;的寫法應該在Build時就會引發Cannot convert null to 'int' because it is a non-nullable value type的錯誤,還是我誤解了您的意思?

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<May 2007>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication