ref和out都是C#中的关键字,所实现的功能也差不多,都是指定一个参数按照引用传递。对于编译后的程序而言,它们之间没有任何区别,也就是说它们只有语法区别。总结起来,他们有如下语法区别:
1、ref传进去的参数必须在调用前初始化,out不必,即:
int i; SomeMethod( ref i );//语法错误 SomeMethod( out i );//通过
2、ref传进去的参数在函数内部可以直接使用,而out不可:
public void SomeMethod(ref int i) { int j=i;//通过 //... } public void SomeMethod(out int i) { int j=i;//语法错误 }
3、ref传进去的参数在函数内部可以不被修改,但out必须在离开函数体前进行赋值。
总结:
应该说,系统对ref的限制是更少一些的。out虽然不要求在调用前一定要初始化,但是其值在函数内部是不可见的,也就是不能使用通过out传进来的值,并且一定要赋一个值。也就是说函数承担初始化这个变量的责任。
如下示例一个简单的使用。
1.OUT
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Text(out string name , out string sex, out string age) { name = "louis"; sex = "male"; age = "25"; } static void Main(string[] args) { string name, sex, age; Text(out name,out sex,out age); Console.WriteLine("My name is {0},I'm {1},I'm {2}", name, sex, age); Console.ReadKey(); } } }
2.REF
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void TextOut(out string name , out string sex, out string age) { name = "louis"; sex = "male"; age = "25"; } static void TextRef(ref string name, ref string sex, ref string age) { name = "ice"; sex = "female"; age = "24"; } static void Main(string[] args) { //string name, sex, age; //TextOut(out name,out sex,out age); string name = "louis"; string sex = "male"; string age = "25"; TextRef(ref name, ref sex, ref age); Console.WriteLine("My name is {0},I'm {1},I'm {2}", name, sex, age); Console.ReadKey(); } } }
很多童鞋要问了,我们不是有引用类型吗?那干嘛还要用ref和out呢?对,我们是有引用类型,可是用out和ref的话就可以把数值类型也当成引用类型了,那不是很方便了?可能调用方方法要接受多个数值类型的变量,而且要对传入的多个数值类型变量都要做操作。传递引用的话,不是可以很方便么?!是吧?当然,不全只是为了方便,我们需要是了解实质。当传递一个数值对象的时候,是传递这个对象的一个副本到被调用方的方法,而传递一个REF和OUT参数呢,是传递这个对象的引用,那么在被调用方就能实际操作被传递进来的对象的实际版本咯。2者差距,是本质的,是吧?
嗯,当然,ref和out不仅只是为值类型对象而存在的,他们也能包装引用类型的对象。
这里有一点要注意:1.使用ref和out传递值的话,在调用方和被调用方方法都要显示注明这2个关键字。
2.ref和out修饰的参数是不作为方法的签名考虑。意思是说,如果有2个方法的签名除了参数包装的关键字只是相差ref和out的话,那么这2个方法的签名是被认为一样的,不是重载。如下代码:
static void Test(out string name); static void Test(ref string name);//这2个方法被编译了以后,是一样的,不能认为是重载了。
但是如下的2个方法就认为是重载了
static void Test(string name); static void Test(ref string name);