C# 引用类型与ref

 1、首先来解释一下C#中的类型

     在C#中每一种类型要么是值类型,要么是引用类型。所以每个对象要么是值类型的实例,要么是引用类型的实例。并且在C#中对象的分配模式取决于对象的实现方式,即值类型使用静态分配,引用类型使用动态分配。即便是在进行值类型实例化的时候使用new关键字进行实例化也不会改变实例的分配方式,在这种情况下new操作法仅起到向构造函数传递参数的作用。

     C#中的引用是一个不同于引用类型的概念,它介于C++中的指针和引用之间。可以是一个到对象的引用,所有该对象的可访问成员都可以通过“.”操作法进行访问;引用可以为空;引用可以被修改(这里要注意在方法参数中使用ref关键字的结果) ;不能够访问对象的物理空间,即对象的实际地址。

2、引用类型和值类型代码示例

  

[c-sharp]  view plain  copy
  1. //TypeVal 是值类型,因为它是一个结构体  
  2. struct TypeVal  
  3. {  
  4.     public int _i;  
  5.     public TypeVal(int i) { _i = i; }  
  6. }  
  7. //TypeRef 引用类型  
  8. class TypeRef  
  9. {  
  10.     public int _i;  
  11.     public TypeRef(int i) { _i = i; }  
  12. }  
  13.   
  14. class Program  
  15. {  
  16.     static void Main()  
  17.     {  
  18.         //创建一个值类型的实例  
  19.         TypeVal v1 = new TypeVal(6);  
  20.         //此处创建一个新的TypeVal类型的实例,v1和v2是两个不同的对象  
  21.         //这两个对象的实例被保存在当前的线程栈中,一般我们称之为变量  
  22.         TypeVal v2 = v1;  
  23.   
  24.         v2._i = 10;  
  25.         //  
  26.         System.Diagnostics.Debug.Assert(v1._i == 6 && v2._i == 9);  
  27.   
  28.         //创建一个 TypeRef 的对象,该语句实际上创建了一个存放于进程堆中的对象  
  29.         //r1本身存在于线程栈上,r1实际上是对新创建对象的引用  
  30.         TypeRef r1 = new TypeRef(6);  
  31.         //r2引用了r1所引用的对象,即一个实际的对象实例,两个指向对象的引用  
  32.         TypeRef r2 = r1;  
  33.   
  34.         r2._i = 11;  
  35.   
  36.         System.Diagnostics.Debug.Assert(r1._i == 11 && f2._i == 11);  
  37.     }  
  38. }  

3、在方法中修改引用类型的范例

 

[c-sharp]  view plain  copy
  1. class RefTest  
  2. {  
  3.     public int Number = 0;  
  4.   
  5.     //使用ref 关键字相当于C++中的双指针  
  6.     //按照引用类型ref 传递引用类型参数允许主调方法直接操作引用,即被调用的方法能够修改  
  7.     //主调方法的的引用所引用的对象。  
  8.     public static void fct(ref RefTest RefA, RefTest RefB)  
  9.     {  
  10.         if (RefA == null)  
  11.             RefA = new RefTest();  
  12.         if (RefB == null)  
  13.             RefB = new RefTest();  
  14.     }  
  15. }  
  16.   
  17.   
  18. class Program  
  19. {  
  20.     static void Main(string[] args)  
  21.     {  
  22.         f_RefTest();  
  23.     }  
  24.     static void f_RefTest()  
  25.     {  
  26.         RefTest refA = null;  
  27.         RefTest refB = null;  
  28.         RefTest.fct(ref refA, refB);  
  29.   
  30.         if (refA == null)  
  31.             System.Console.WriteLine("refA is null");  
  32.         else  
  33.             System.Console.WriteLine("refA now references the RefTest allocated in fct");  
  34.         if (refB == null)  
  35.             System.Console.WriteLine("refB is null");  
  36.         else  
  37.             System.Console.WriteLine("refB now references the RefTest allocated in fct");  
  38.   
  39.         System.Console.ReadLine();  
  40.     }  

输出结果如下:

可见对于添加ref关键字的引用类型,其效用就在于能够在方法内部对引用的指向进行修改。如果不添加ref关键字,那么其作用仅限于通过引用修改该引用所指向的对象的内部状态(对象的字段等)。

4、ref 与string

C#中string类具有三大特点,即sealed、等价比较、实例创建后的不可变性。

[c-sharp]  view plain  copy
  1. static void TestString(ref string str1, string str2)  
  2. {  
  3.   
  4.     //此处创建了一个新的string实例,并修改了str1引用的指向  
  5.     str1 = "new str1";  
  6.     //创建一个新的string实例,在方法内部修改str2的引用  
  7.     str2 = "new str2";  
  8. }  
  9.   
  10. static void Main(string[] args)  
  11. {  
  12.     //f_RefTest();  
  13.   
  14.     string str1 = "str1";  
  15.     string str2 = "str2";  
  16.   
  17.     TestString(ref str1, str2);  
  18.   
  19.     Console.WriteLine(str1);  
  20.     Console.WriteLine(str2);  
  21.     Console.ReadLine();  
  22. }  

 

 

 

5、总结

ref(引用型参数)对方法的数据传递是通过实际值的内存地址来传递的,所以说对其的改变将影响到它实际的内存地址。如果ref 作用于引用类型,那么意味着可以修改引用本身的值,即修改引用的指向。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值