前兩天一個朋友問我,想實現一個輕量級的Dictionary<string,object>, 俺告訴他使用 System.Collections.Specialized.HybridDictionay, 它可以根據無素的數量自動選擇內部的資料存放區結構, 應該說是一個比較理想的選擇, 後來又談到, 如果在裡面儲存 <string,string>會不會引發裝拆箱操作,因為string是實值型別的, string在.net中是一個比較特殊的類型,它表現出來是實值型別,但是準確的講它應該是"內建的參考型別", 因此對於上面的操作不會引發裝拆箱的操作. 為了驗證這個說法寫了一段程式: 反組譯碼結果如下: 1.method private hidebysig static void Main(string[] args) cil managed
2{
3 .entrypoint
4 // Code size 127 (0x7f)
5 .maxstack 2
6 .locals init ([0] int32 integer,
7 [1] object o,
8 [2] int32 int2,
9 [3] string str,
10 [4] object oString,
11 [5] string str2)
12 IL_0000: nop
13 IL_0001: ldc.i4 0x3e7
14 IL_0006: stloc.0
15 IL_0007: ldstr "Origin integer value is : "
16 IL_000c: ldloca.s integer
17 IL_000e: call instance string [mscorlib]System.Int32::ToString()
18 IL_0013: call string [mscorlib]System.String::Concat(string,
19 string)
20 IL_0018: call void [mscorlib]System.Console::WriteLine(string)
21 IL_001d: nop
22 IL_001e: ldloc.0
23 IL_001f: box [mscorlib]System.Int32
24 IL_0024: stloc.1
25 IL_0025: ldloc.1
26 IL_0026: call int32 [mscorlib]System.Convert::ToInt32(object)
27 IL_002b: stloc.2
28 IL_002c: ldstr "The unbox interger value is : "
29 IL_0031: ldloca.s int2
30 IL_0033: call instance string [mscorlib]System.Int32::ToString()
31 IL_0038: call string [mscorlib]System.String::Concat(string,
32 string)
33 IL_003d: call void [mscorlib]System.Console::WriteLine(string)
34 IL_0042: nop
35 IL_0043: ldstr "Hello world!"
36 IL_0048: stloc.3
37 IL_0049: ldstr "Orgine string value is :"
38 IL_004e: ldloc.3
39 IL_004f: call string [mscorlib]System.String::Concat(string,
40 string)
41 IL_0054: call void [mscorlib]System.Console::WriteLine(string)
42 IL_0059: nop
43 IL_005a: ldloc.3
44 IL_005b: stloc.s oString
45 IL_005d: ldloc.s oString
46 IL_005f: callvirt instance string [mscorlib]System.Object::ToString()
47 IL_0064: stloc.s str2
48 IL_0066: ldstr "Unbox string value is : "
49 IL_006b: ldloc.s str2
50 IL_006d: call string [mscorlib]System.String::Concat(string,
51 string)
52 IL_0072: call void [mscorlib]System.Console::WriteLine(string)
53 IL_0077: nop
54 IL_0078: call string [mscorlib]System.Console::ReadLine()
55 IL_007d: pop
56 IL_007e: ret
57} // end of method Program::Main
來源程式:
static void Main(string[] args)
{
int integer = 999;
Console.WriteLine("Origin integer value is : " + integer.ToString());
object o = (object)integer;
int int2 = Convert.ToInt32(o);
Console.WriteLine("The unbox interger value is : " + int2.ToString());
string str = "Hello world!";
Console.WriteLine("Orgine string value is :" + str);
object oString = (object)str;
string str2 = oString.ToString();
Console.WriteLine("Unbox string value is : " + str2);
Console.ReadLine();
}
注意到在反編出來的代碼中的23行執行了裝箱操作,但是對於後面的字串轉為Object確沒有進行box.
另外, 由於一個字串在.net中一旦被建立出來就不可更改,可以認為CLR在記憶體維護了一個字串的字典, 對於字串的更改會在這個字典中尋找是否已經存在,否則就再建立一新的字串. 因此於對這樣的操作: Console.Write(str1 + str2)最好寫成 Console.Write(str1), Console.Write(str2), 否則將產生一個新的字串.