对于 ref 和out 网上一搜一大堆,目前看的基本就是照《C#图解教程》说的。对这个两个概念有些困惑,自己看了《C#图解教程》后豁然开朗。网上看不明白的同学,建议购买这本书或者找PDF资源,看看第5章的5.10、5.11、5.12、5.13,里面讲得很详细,结合图例非常好理解。下面讲一点自己的见解,可能说得有些拗口,但只是记录自己的想法,看不懂的移步课本,绝对能理解。
引用参数(ref)
网上看到有些人说,当参数是对象时,ref可以不用写,如下图。这样想其实是有误的,加不加还是有一点区别的。
这里有必要解释一下,当参数是对引用类型,即string或者类对象时,不用ref确实也能达到在方法中修改实参的目的。但是,加ref和不加ref还是有一定区别的。
这里我们先想一下值类型参数加ref的情况。值类型参数加ref类似于C++的引用,即形参作为实参的别名。而引用类型变量本身就是一个引用,引用类型形参加ref后,形参就是这个引用的别名,即形参引用和实参引用绑定到一起。但是如果引用类型形参不加ref的话,即是将引用类型实参的引用复制给引用类型形参,并不是别名,也就没有绑定到一起,这里其实有一点是和加了ref一样的,那就是指向相同地址,这时如果对该地址进行数据操作,确实看起来和加了ref一样,但是一旦方法内形参重新指向新地址的话,实参可不会跟着改变。
总结:引用类型,
- 加ref :实参和形参是互为别名的引用,指向同一地址,指向的内容改变,两个同时改变,一个重定向地址,另一个也重定向地址;
- 不加ref:实参和形参只是复制关系,是两个独立的引用,同时指向同一地址,指向的内容改变,两个都改变,但如果重定向地址,另一个引用并不会跟着重定向。
输出参数(out)
out和ref类似,但也有点不同:
- 引用参数的实参前传入方法前必须赋值,哪怕是赋值为引用或者null(这两个相对于引用变量);而输出参数则不用,但是输出参数必须在方法内部被读取之前赋值,如果方法内没有读取这个输出参数,则必须在方法返回之前赋值。从字面意思就可以理解了,ref是引用参数,你传参时没赋值,拿头引用吗?out是输出参数,这个参数输出之前,即无论是在方法内被读取还是函数返回之前,如果没赋值,拿毛线输出,所以其实理解起来并不难,从字面加以理解就可以了。