C#中的String类型
前两天一个朋友问我,想实现一个轻量级的Dictionary<string,object>, 俺告诉他使用 System.Collections.Specialized.HybridDictionay, 它可以根据无素的数量自动选择内部的数据存储结构, 应该说是一个比较理想的选择, 后来又谈到, 如果在里面存储 <string,string>会不会引发装拆箱操作,因为string是值类型的, string在.net中是一个比较特殊的类型,它表现出来是值类型,但是准确的讲它应该是"内置的引用类型", 因此对于上面的操作不会引发装拆箱的操作. 为了验证这个说法写了一段程序: 反汇编结果如下:
注意到在反编出来的代码中的23行执行了装箱操作,但是对于后面的字符串转为Object确没有进行box.
另外, 由于一个字串在.net中一旦被创建出来就不可更改,可以认为CLR在内存维护了一个字符串的字典, 对于字符串的更改会在这个字典中查找是否已经存在,否则就再创建一新的字串. 因此于对这样的操作: Console.Write(str1 + str2)最好写成 Console.Write(str1), Console.Write(str2), 否则将产生一个新的字串.
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
源程序: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();
}
{
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), 否则将产生一个新的字串.