今天来讲讲ref和out关键字的前世今生
前言
C#中数据类型分为值类型和引用类型
干货:
方法声明的参数列表中的参数叫做形参,实际调用方法时传递给方法的参数叫做实参,调用方法时,程序会首先将实参的值传递给对应的形参,而后执行方法体中的代码。对于引用类型的参数,实参和形参会指向同一个对象。而对于值类型的参数,实参的值将被复制一份给形参,方法代码中的对形参的修改不会影响到实参。
为了解决这一问题,C#中提供了方法参数的引用传递方式,ref关键字。
此时形参是实参的”引用”,二者指向同一个变量,如果代码中修改了形参的值,实参的值也会改变,这样就能真正起到交换参数值的效果了。
先来看一个栗子:
//一会要用到的方法
private void CorrectCount(int count)
{
count = 11;
}
private void CorrectCount(ref int count)
{
count = 11;
}
int count = 0;
Debug.Log("Origin count: " + count);
CorrectCount(count);
Debug.Log("Correct count: " + count);
CorrectCount(ref count);
Debug.Log("Correct count ref : " + count);
//输出:
Origin count: 0
Correct count: 0
Correct count ref : 11
我们再看一个特殊的栗子:
//一会要用到的方法
private void CorrectCount(string count)
{
count = "11";
}
private void CorrectCount(ref string count)
{
count = "11";
}
string count = "0";
Debug.Log("Origin count: " + count);
CorrectCount(count);
Debug.Log("Correct count: " + count);
CorrectCount(ref count);
Debug.Log("Correct count ref : " + count);
//输出:
Origin count: 0
Correct count: 0
Correct count ref :11
嗯?刚刚不是说,ref是为了解决值类型无法在方法内外真正交换参数值的问题吗? string 明明是引用类型,为啥子也不能【黑人问号脸】
这里需要特别注意的是,string虽然是引用类型,但这个东东太特殊了,C#对它进行了特殊处理,虽然它本身是引用类型,但相关操作都会导致它产生一个新的string对象,你看,你传进去是小明,人家在里面改了名字叫老王了。所以如果是string类型,也要用ref。
那还有其他的吗。不,没了,其他的引用类型(就剩class了)随便用。就算你class里面定义了很多值类型,在方法里面也修改了, 没得关系。但如果你的实参直接是class.int 对不起,你这个是值类型。
ref弄透彻了,再来说说它兄弟out
out关键字,加了它的就叫输出型参数(ref 是引用型参数)。其实两个用法差不多,只是有一些小区别罢了。
那就来看看他们的区别把:
round one:
ref:我可进可出(可以传值进来,我也可以传出去)
out:我只出不进(不能传值进来,但我可以传出去)
round two:
ref:进来之前必须初始化
out:进来之前爱咋地咋地,进来后,我就给你初始化(必须赋值才能出)
round three:
ref:我们俩兄弟不能构成重载
out:对,我们俩兄弟不能构成重载(如果两个方法只是ref和out关键字不同,其他的方法名/参数类型等都相同的话,不构成重载,编译器会报错)
举个简单的out的栗子:
private void CorrectCountOut(out int count)
{
count = 33;
}
int count;
CorrectCountOut(out count);
Debug.Log("Correct count out: " + count);
//输出
Correct count out: 33