标签:
C#中存在两种数据类型,分别是值类型与引用类型,下面我们来看看这两种类型的区别。
值类型主要包括:
引用类型主要包括:
值类型的实例大部分情况下会被存放在线程的堆栈上,由操作系统管理其在内存上的分配和释放。
引用类型的实例都会被存放在托管堆上,由垃圾回收器(GC)管理其在内存上的分配和释放。
1 namespace Study 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 int valueType = 0; 8 string refType = "abc"; 9 } 10 } 11 }
上面的示例中:
valueType是值类型,其变量名和值都会被存储到堆栈中。
refType是引用类型,其变量名任然存储在堆栈中,但是其值"abc"是存储在托管堆中的。
1 namespace Study 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Test test = new Test(); 8 } 9 } 10 11 public class Test 12 { 13 private int valueType = 0; 14 } 15 }
上例中的Test作为引用类型被分配到托管堆中,其属性valueType虽然是值类型,但是仍然也会被分配到托管堆中。
装箱是指值类型转换为引用类型的过程,拆箱表示将引用类型转换为值类型的过程。
装箱和拆箱堆性能有一定影响,所以我们需要需要尽量避免。
形参值方法中定义的参数,实参指实际传递给方法的参数。
形参作为从实参拷贝的一个副本,对形参的修改不会影响到实参。
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 int num = 100; 10 Func(num); 11 12 Console.WriteLine("num: " + num); 13 14 Console.Read(); 15 } 16 17 private static void Func(int i) 18 { 19 i++; 20 21 Console.WriteLine("i: " + i); 22 } 23 } 24 }
结果如下:
1 i: 101 2 num: 100
形参作为从实参拷贝的一个副本,但是由于是引用类型记录的是内存地址,所以两个参数实际都指向托管堆中的同一个对象,故对形参的修改会影响到实参。
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Test t = new Test(); 10 t.num = 50; 11 Func(t); 12 13 Console.WriteLine("Main: " + t.num); 14 15 Console.Read(); 16 } 17 18 private static void Func(Test test) 19 { 20 test.num = 100; 21 22 Console.WriteLine("Func: " + test.num); 23 } 24 } 25 26 public class Test 27 { 28 public int num = 0; 29 } 30 }
结果如下:
1 Func: 100 2 Main: 100
string对象虽然是引用类型,但是由于string类型具备的不变性,在传递参数后实际上在内存中重新拷贝了一份数据。
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 string str = "old string"; 10 Func(str); 11 12 Console.WriteLine("Main: " + str); 13 14 Console.Read(); 15 } 16 17 private static void Func(string s) 18 { 19 s += ", new string"; 20 21 Console.WriteLine("Func: " + s); 22 } 23 } 24 }
结果如下:
1 Func: old string, new string 2 Main: old string
当需要直接传递参数的引用到函数内部时,通过引用传递参数允许函数成员更改参数的值,并保持该更改,需要使用ref和out关键字来实现:
下面我们看一个例子:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 int num = 23; 10 FuncInt(ref num); 11 Console.WriteLine("MainInt: " + num); 12 13 string str = "old string"; 14 FuncStr(ref str); 15 Console.WriteLine("MainStr: " + str); 16 17 Console.Read(); 18 } 19 20 private static void FuncInt(ref int i) 21 { 22 i += 100; 23 24 Console.WriteLine("FuncInt: " + i); 25 } 26 27 private static void FuncStr(ref string s) 28 { 29 s += ", new string"; 30 31 Console.WriteLine("FuncStr: " + s); 32 } 33 } 34 }
结果如下:
1 FuncInt: 123 2 MainInt: 123 3 FuncStr: old string, new string 4 MainStr: old string, new string
如果是out关键字则不能初始化实参,如下:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 int num; 10 FuncInt(out num); 11 Console.WriteLine("MainInt: " + num); 12 13 string str; 14 FuncStr(out str); 15 Console.WriteLine("MainStr: " + str); 16 17 Console.Read(); 18 } 19 20 private static void FuncInt(out int i) 21 { 22 i = 100; 23 24 Console.WriteLine("FuncInt: " + i); 25 } 26 27 private static void FuncStr(out string s) 28 { 29 s = ", new string"; 30 31 Console.WriteLine("FuncStr: " + s); 32 } 33 } 34 }
结果如下:
1 FuncInt: 100 2 MainInt: 100 3 FuncStr: , new string 4 MainStr: , new string
标签:
原文地址:http://www.cnblogs.com/hammerc/p/4608347.html