C#用ref关键字修饰引用型参数传参有何不同
这是在博客园的第一篇日志(当然不会是最后一篇),一直都想有一个技术型博客,曾经开过独立的WordPress不过维护起来很麻烦,找来找去还是到博客园这里安家了.在这里来分享一个正在不断前行的大三软件工程专业童鞋在学习过程中遇到的问题以及解决方案.才疏学浅肯定有不足之处,望各位多多纠正,多多包涵...
好了,进入正题.
在C#中,变量分为两种类型:一种是值类型,另一种是引用类型.任何称为"类"的类型都是引用类型,而任何结构和枚举都是值类型(System.Int32结构,System.DayOfWeek枚举).在方法间传递参数的时候,普通的传递参数都是传值的. 在传递引用类型的对象时,对一个对象的引用会传递给方法.也就是说,目标方法(被调用者)可以修改对象的成员,而源方法(调用者)可以看到这些修改.对于传递值类型的参数,目标方易做图获得这个值类型的副本进行处理,而源方法的值类型实例不受到影响.(本段引用 CLR Via C#中的解释)
另一方面,如果在传递参数的时候,使用ref关键字进行修饰的话,会以传引用的方式传递参数.对于值类型来说,直接把值类型的引用(指针)传递给目标方法,修改结果会影响到源方法中的值类型.但是对于引用类型来说,普通传参已经是传引用了,那么再用ref关键字修饰会是什么样的结果? 当时想了半天也没想明白这个过程,Google之后发现是这样的:
先看一下针对这个问题写的代码:
using System;
namespace CSharpConsole
{
public class DemoClass
{
public int ID;
public DemoClass(int id)
{
ID = id;
}
}
class Program
{
static void Main(string[] args)
{
DemoClass a = new DemoClass(10);
ShowID("什么都没做,初始化时", a);
ChangeIDWithoutRef(a);
ShowID("通过普通传递参数方式更改成员变量", a);
ChangeIDWithRef(ref a);
ShowID("通过Ref关键字传递参数方式更改成员变量", a);
ChangeObjectItselfWithoutRef(a);
ShowID("通过普通传递参数方式更改对象本身", a);
ChangeObjectItselfWithRef(ref a);
ShowID("通过Ref关键字传递参数方式传递更改对象本身", a);
Console.Read();
}
private static void ChangeIDWithRef(ref DemoClass c)
{
c.ID += 10;
}
private static void ChangeIDWithoutRef(DemoClass c)
{
c.ID += 10;
}
private static void ChangeObjectItselfWithRef(ref DemoClass c)
{
c = new DemoClass(100);
}
private static void ChangeObjectItselfWithoutRef(DemoClass c)
{
c = new DemoClass(100);
}
private static void ShowID(string msg ,DemoClass c)
{
Console.WriteLine(string.Format("{0} Now ID is: {1}", msg, c.ID));
}
}
}
控制台输出结果是
什么都没做,初始化时 Now ID is: 10
通过普通传递参数方式更改成员变量 Now ID is: 20
通过Ref关键字传递参数方式更改成员变量 Now ID is: 30
通过普通传递参数方式更改对象本身 Now ID is: 30
通过Ref关键字传递参数方式传递更改对象本身 Now ID is: 100
结论出来了.使用ref关键字传递引用类型参数时,传递的是对象的地址,而不是对象地址的副本,目标方法可以修改这个引用类型参数的地址,并且可以用另一个对象替换源方法中的对象.
为了理解这个过程,可以把引用类型看作值类型,它的值就是它引用的地址,普通传参的时候会把这个值复制一份传递给目标方法,不论目标方法怎么修改这个值,源方法中的值没有变,依旧指向原来的那个对象的地址.而如果用了ref修饰之后,传递的就是这个值的引用,目标方法能够直接修改源方法中的值,会使得源方法的值改变,源方法的引用类型就会指向其他对象的地址.
这样解释还算可以理解吧.
摘自 程序猿WonTasia的万事屋
补充:软件开发 , C# ,