ref和out
横眉冷对千夫指,俯首甘为孺子牛。
首先明确C#两大数据类型分别是值类型数据和引用类型数据。
值类型数据:直接存储其值,存储在堆栈当中(stack),变量间赋值是值拷贝。
引用类型数据:存储的是对值的引用,存储在托管堆当中(heap),变量间赋值时是地址拷贝。
值类型:
整型:byte(0~255),sbyte(-128~127),short,ushort,int,uint,long,ulong
浮点类型:float,double
bool类型:bool
字符类型:char
枚举(enum),结构(struct)
引用类型:
object(所有的类的基类是object),string,类等等
ref参数:
![v2-8f839b377389f3e3f357de27dc7398b8_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/bc6264b04a840d9125003da08b66b255.png)
我们都知道上述代码执行,结果肯定是100。变量的有效性是有作用域的,c本身只在main方法中起作用。但是我们可以通过引用传递值类型,添加ref修饰符,使得可以传递c对象本身。
![v2-052a1aca18f50bf330a54e1d8e76a1a7_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/53220416d6e6bd4b9f323027c32f761a.png)
![v2-71d77c55a3a7515f9737fc3727e54926_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/954a301c59571d679ff677d6ef8102c6.png)
这里为什么说是c对象本身,而不是c的值呢?
因为假如c是类,引用类型,在方法外是可以更改传递过来的对象里面的属性的,但无法更改其指向的引用对象的地址。下面举例说明
![v2-5c9b7ea56ac7d285819751739d4a6e75_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/dfa5a4f8f2d187285ad56398612ba387.jpeg)
大家觉得,输出结果会是多少呢?
答案是2,而不是3.如下图所示
![v2-bc4d749ee415eccf29bf1cad79a7ad5d_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/74101ef3ff2602e5c814448a97ff025b.jpeg)
未调用方法之前,栈中a存入的是相对应在堆中的引用地址,调用更改值的方法时,更改了其x的值,但是new 只是在堆中新建了一块内存空间,因为传递过来的只是一个引用,并不是对象本身,并不能改变其指向地址,所以方法结束之后,new的对象就被回收了。
这时加上ref关键字,就可传递a对象本身。如下图,输出结果为3.
![v2-caf6e77b57ea7e17415fdddab9be9e18_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/d5a9b8aa79096f4613ecaa4065e29b27.jpeg)
out参数:
如果方法返回多个值,可能类型还不同,该怎么办?这里有不同的选项。第一种就是定义dto,将要返回的全部定义为model的成员;第二种就是使用元组类型:Tuple<T1,T2,T3...>;第三种就是使用out关键字。
Tuple元组:
![v2-79aa5292bf0b2a642631ae0b8f1eba96_b.png](https://i-blog.csdnimg.cn/blog_migrate/69a80b0005e3cdd3a34253574c23e22c.png)
![v2-38ae28b3b4dbea9a2d7f278cb5be3eb1_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/15258c794f8fb5f74c2bb9ea928a3091.jpeg)
![v2-cfcc86065c6b3230b7259e2e608d8124_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/934b5b2d4218346ee4c12aa4b7143916.png)
out参数:
![v2-a3bfb9a37a7ec07e6d3fc2e14f962c96_b.png](https://i-blog.csdnimg.cn/blog_migrate/2322a96babb6b768f08c7ab558444f91.png)
c变量不需要预先初始化,但是在方法内必须赋值,而ref则不必一定要在方法内赋值。