ref out 区别

首先:两者都是按地址传递的,使用后都将改变原来参数的数值。(传递过来参数,之后对参数修改会影响调用时的参数的值)

其次:ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所以你必须初始化一次。这个就是两个的区别,或者说就像有的网友说的,ref是有进有出,out是只出不进。

ref(C# 参考)

ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class  RefExample
{
     static  void  Method( ref  int  i)
     {
         i = 44;
     }
 
     static  void  Main()
     {
         int  val = 0;
         Method( ref  val);
         // val is now 44
     }
}

 

传递到 ref 参数的参数必须最先初始化。这与 out 不同,后者的参数在传递之前不需要显式初始化。

尽管 ref 和 out 在运行时的处理方式不同,但在编译时的处理方式相同。因此,如果一个方法采用 ref 参数,而另一个方法采用 out 参数,则无法重载这两个方法。例如,从编译的角度来看,以下代码中的两个方法是完全相同的,因此将不会编译以下代码:

1
2
3
4
5
6
7
class  CS0663_Example
{
     // Compiler error CS0663: "cannot define overloaded
     // methods that differ only on ref and out".
     public  void  SampleMethod( ref  int  i) { }
     public  void  SampleMethod( out  int  i) { }
}

 但是,如果一个方法采用 ref 或 out 参数,而另一个方法不采用这两个参数,则可以进行重载,如下例所示:

1
2
3
4
5
class  RefOutOverloadExample
{
     public  void  SampleMethod( int  i) { }
     public  void  SampleMethod( ref  int  i) { }
}

 

out(C# 参考)

out 关键字会导致参数通过引用来传递。这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化。若要使用 out 参数,方法定义和调用方法都必须显式使用out 关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class  OutExample
{
     static  void  Method( out  int  i)
     {
         i = 44;
     }
 
     static  void  Main()
     {
         int  value;
         Method( out  value);
         // value is now 44
     }
}

 尽管作为 out 参数传递的变量不必在传递之前进行初始化,但需要调用方法以便在方法返回之前赋值。

 

ref 和 out 关键字在运行时的处理方式不同,但在编译时的处理方式相同。因此,如果一个方法采用 ref 参数,而另一个方法采用 out 参数,则无法重载这两个方法。例如,从编译的角度来看,以下代码中的两个方法是完全相同的,因此将不会编译以下代码:

1
2
3
4
5
6
7
class  CS0663_Example
{
     // Compiler error CS0663: "Cannot define overloaded
     // methods that differ only on ref and out".
     public  void  SampleMethod( out  int  i) { }
     public  void  SampleMethod( ref  int  i) { }
}

 但是,如果一个方法采用 ref 或 out 参数,而另一个方法不采用这两类参数,则可以进行重载,如下所示:

1
2
3
4
5
class  RefOutOverloadExample
{
     public  void  SampleMethod( int  i) { }
     public  void  SampleMethod( out  int  i) { }
}

 

下面是本人的一些心得

区别:

ref和out的区别在C# 中,既可以通过值也可以通过引用传递参数。通过引用传递参数允许函数成员更改参数的值,并保持该更改。若要通过引用传递参数, 可使用ref或out关键字。ref和out这两个关键字都能够提供相似的功效,其作用也很像C中的指针变量。它们的区别是:

1、使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。

2、使用ref和out时,在方法的参数和执行方法时,都要加Ref或Out关键字。以满足匹配。

3、out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。

out

方法参数上的 out 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。

当希望方法返回多个值时,声明 out 方法非常有用。使用 out 参数的方法仍然可以返回一个值。一个方法可以有一个以上的 out 参数。

若要使用 out 参数,必须将参数作为 out 参数显式传递到方法。out 参数的值不会传递到 out 参数。

不必初始化作为 out 参数传递的变量。然而,必须在方法返回之前为 out 参数赋值。

属性不是变量,不能作为 out 参数传递。

1. 值类型在传递值的时候,只是复制了一份值赋给另一个变量,另一个变量改变并不能改变原有的值。例如:  

            int num = 200;
            int a = num;
            a -= 100;
            Console.WriteLine(num);//输出200
            Console.WriteLine(a);//输出100

   但是,假如num代表我钱包里的钱,我把钱包交给别人(int a=num),别人用了100(a-=100),这时候,我钱包里的钱(num)应该是多少?按照上面的方式执行就会出错,钱包里的钱是不会变的,因为在传值的时候只是复制了num的一份值给a,a改变并不会改变num的值。那该怎么办???

   如果我传递的值是num的引用(可以理解为地址),那么a 改变了num就也会改变了。但是int 类型是值传递,怎么办,把它变为引用就要用到ref和out参数。

  ref和out参数的作用就是把值传递改为引用传递。

  改写上面的钱包的例子。

复制代码
       static void Main(string[] args)
        {
            int num = 200;
            int res =Test(ref num );
            Console.WriteLine(num );//输出100
            Console.WriteLine(res );//输出100
            Console.Read();

        }

        static int Test(ref int a)
        {
            a -= 100;
            return a;
 
        }
复制代码

  在内存图中分析一下ref参数:

  

 2 ref参数可以按引用类型传递,如果ref修饰的是引用类型的参数呢?先看下面的例子:

  先创建一个person类  

复制代码
 private int _age;
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }
复制代码

  再看一下面ref修饰引用类型的情况。

复制代码
     static void Main(string[] args)
        {
            Person p = new Person() { Name ="红红"};
            Test1(p);
            Console.WriteLine(p.Name); //输出什么???
            TestRef1(ref p);
            Console.WriteLine(p.Name);  //输出什么???
            Test2(p);
            Console.WriteLine(p.Name); //输出什么???
            TestRef2(ref p);
            Console.WriteLine(p.Name);  //输出什么???
            Console.Read();
        }
        static void Test1(Person p)
        {
            p = new Person() { Name = "绿绿" };   // 参数指向新申请空间,对之前引用无关系了,所以没修改
        }
        static void TestRef1(ref Person p)
        {
            p = new Person() { Name ="蓝蓝"};   // 参数指向新的空间-但参数和调用时的变量是一个地址,所以修改了值
        }

        static void Test2(Person p)
        {
            p.Name = "嘿嘿";
        }
        static void TestRef2(ref Person p)
        {
            p.Name = "掰掰";
        }
复制代码

 

  输出结果是,红红,蓝蓝,嘿嘿,掰掰。画一下内存图很好分析。引用类型本来传递的就是地址,所以引用类型使用ref参数和不使用是一样的。这里偷一下懒,想知道的去运行,画一下内存图吧!!!

   ref用法:1、使用ref必须在参数声明和调用的时候都带上ref关键字;

       2、只能修饰变量,不能修饰常量;

       3、ref在方法中可以对ref修饰的值不改变,但是在传参前必须给参数赋值;    

out:

  ref 在使用之前必须赋初始值,它主要侧重于改变,修改值。使用ref,在函数声明与调用的时候必须在参数前面加上ref。out参数的作用与使用方法与ref类似,与ref不同的是out在使用前不必赋初始值,但在返回的时候必须为他赋值,所以out主要侧重于输出。out修饰符参数例子:

复制代码
       static void Main(string[] args)
        {
            int num = 200;
            int b;
            int a = TestOut(200,out b);
            Console.WriteLine(a);//输出100
            Console.WriteLine(b);//输出200
            Console.Read();

        }
        static int TestOut(int a,out int b)
        {
            b = a;
            a -= 100;
            return a;

        }
复制代码

 

总结:ref和out参数修饰符,都是把参数按引用类型传递,但是ref侧重于改变值,而out侧重于输出。一个函数只有一个输出值,但想返回多个值的时候就用out参数修饰符。

       ref在使用之前必须赋值,out在返回之前必须赋值。ref和out在函数使用和调用的时候,参数前面必须加ref和out参数。


https://www.cnblogs.com/sunliyuan/p/5999045.html

https://www.cnblogs.com/wangliu/p/3876672.html

猜你喜欢

转载自blog.csdn.net/july_unity/article/details/80836984