日期:2014-05-17  浏览次数:20985 次

C#有out又何须ref?

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);

?