ref与out之间的区别整理美高梅4858官方网站

作者:编程技术

简单说就是ref有进有出(或无出),out无进有出。

Ref 把值传递变成引用传递

 

一个函数中,使用out或ref作为形参前的关键字,那么在函数体中只要修改过这个形参,之前调用这个函数时赋给对应形参的实参的值也会修改。这是怎么实现的呢?它的机理就是,使用out 和ref修饰的形参是引用类型,而不是值类型,也就是说它们所存储的信息是地址,而不是值类型。

 

ref在参数传递之前必须初始化;而out则在传递前不必初始化,且在 ... 值类型与引用类型之间的转换过程称为装箱与拆箱。

既然都是存储的地址,那么它们有什么区别呢?
我整理了一下,主要有以下几点区别:
1,ref 要求变量必须在传递之前进行初始化(赋初值),但调用时可以对它什么也不做;而out 在调用*之前*,并不需要为这一形参的变量赋予初始值。
2,out 只能用来将值从方法中传出。不管外界是什么值,使用了out是要把参数清空的,然后函数体中必须对其赋值。也就是说,在调用*之时*的函数体内部必须对out修饰的变量赋值。

 

下面谈谈ref和out到底有什么区别:

 

美高梅4858官方网站 1

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

当写代码要返回多个值的时候,当然可以返回一个数组来实现,但如果遇到需要返回的多个值的类型不同呢?这个时候怎么办?

 

          out作为参数的函数在调用前,实参可以不赋初始值。

不知大家有没有遇到过需要一个函数返回多个值的情况。

OUT 让方法返回多个值

 

c#中,out关键字和ref关键字就起作用了。(且out更适合用到多返回值的地方)

 

总结:
应该说,系统对ref的限制是更少一些的。out虽然不要求在调用前一定要初始化,但是其值在函数内部是不可见的,也就是不能使用通过out传进来的值,并且一定要在函数内赋一个值。或者说函数承担初始化这个变量的责任。

class Program
    {

            static void Main(string[] args)
            {
               Program pg = new Program();
                int x =0;
                int y = 0;
                pg.getnull(ref x, ref y);//这里x,y必须为已经赋过初值的,否则编译不通过
                Console.WriteLine("x="   x   ",y="   y);//输出为:x=0,y=0,原值没有改变,因为是空方法

                pg.GetValue(ref x, ref y);//这里x,y已经赋过初值的
                Console.WriteLine("x="   x   ",y="   y);//输出为:x=1,y=2
                Console.ReadLine();

            }
            public void getnull(ref int x, ref int y)
            {

            }
            public void GetValue(ref int x, ref int y)
            {
                x  ;
                y = y   2;
            }

    }

 class Program
    {

            static void Main(string[] args)
            {
               Program pg = new Program();
                int x =0;
                int y = 0;
                pg.getnull(out x,out y);//这里x,y不需要赋初值,赋了也没关系,但会清零;注意:** 调用函数时必须写关键字out ** 因为参数与关键字是一起传递的
                Console.WriteLine("x="   x   ",y="   y);//输出为:x=3,y=3,原值没有改变,因为是空方法

                pg.GetValue(out x, out y);//这里x,y已经赋过初值的
                Console.WriteLine("x="   x   ",y="   y);//输出为:x=12,y=21
                Console.ReadLine();

            }

            public void getnull(out int x, out int y)//如果函数体中没有给x,y赋初值(即下面函数体为空),那么编辑器会提示“控制离开当前方法之前必须对out参数x赋初值”,编译不通过
            {
                x = 3;//这里我们赋值,不赋值编译不通过
                y = 3;
            }
            public void GetValue(out int x, out int y)
            {
                //x  ;//同样如果这么写会提示“使用了未赋值的out参数 x”,所以不可以这么直接 x  
                //y = y   2;//同上

                //我们改为下边写法,就可以编译通过
                x = 12;
                y = 12;
            //这个函数和getnull的功能就完全相同了
             }
    }

ref和out有着异曲同工之妙,都可以实现相同的功能,ref侧重于将值类型的值传递改变为引用传递,out侧重于对于一个方法返回多个值

 

示例代码如下,

结论:

ref(C# 参考)

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

例如:

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 参数,则无法重载这两个方法。例如,从编译的角度来看,以下代码中的两个方法是完全相同的,因此将不会编译以下代码:

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 参数,而另一个方法不采用这两个参数,则可以进行重载,如下例所示:

class RefOutOverloadExample

{

    public void SampleMethod(int i) { }

    public void SampleMethod(ref int i) { }

}

 

 

美高梅4858官方网站 2

}

 

 

 

输出结果:101

ref和out都是C#中的关键字,所实现的功能也差不多,都是指定一个参数按照引用传递。

使用ref关键字的时候需要注意:

   原则:在被调用函数内,out引入的参数在返回前至少赋值一次,否则编译器将提示:使用了未赋值的out参数;

使用out关键字需要注意:

1 关于重载

 

3、ref传进去的参数在函数内部可以不被修改,但out必须在离开函数体前进行赋值。

 

          在被调用函数内,ref引入的参数在返回前不必为其赋初值。

结论:

2、ref传进去的参数在函数内部可以直接使用,而out不可:
public void SomeMethod(ref int i)
{
   int j=i;//通过
   //...
}
public void SomeMethod(out int i)
{
   int j=i;//语法错误

 

 

1.在方法定义和方法调用时,都要加上out关键字

3 关于在函数内,引入的参数初始值问题

 

 

 

总结起来,他们有如下语法区别:

ref与out的区别是什么?

首先:两者都是按地址传递的,使用后都将改变原来参数的数值。


1、ref传进去的参数必须在调用前初始化,out不必,即:
int i;
SomeMethod( ref i );//语法错误
SomeMethod( out i );//通过

作用总结:如果想使一个值类型的变量,通过传入一个方法进行改变,可以使用ref

    原则:ref作为参数的函数在调用前,实参必须赋初始值。否则编译器将提示:使用了未赋值的局部变量;

 

总结:C#中的ref和out提供了值类型按引用进行传递的 解决方案,当然引用类型也可以用ref和out修饰,但这样已经失去了意义。因为引用数据类型本来就是传递的引用本身而非值的拷贝。ref和out关键字 将告诉编译器,现在传递的是参数的地址而不是参数本身,这和引用类型默认的传递方式是一样的。同时,编译器不允许out和ref之间构成重载,又充分说明 out和ref的区别仅是编译器角度的,他们生成的IL代码是一样的。有人或许疑问,和我刚开始学习的时候一样的疑惑:值类型在托管堆中不会分配内存,为 什么可以按地址进行传递呢?值类型虽然活在线程的堆栈中,它本身代表的就是数据本身(而区别于引用数据类型本身不代表数据而是指向一个内存引用),但是值 类型也有它自己的地址,即指针,现在用ref和out修饰后,传递的就是这个指针,所以可以实现修改后a,b的值真正的交换。这就是ref和out给我们 带来的好处。

2.作为传入修饰了ref的方法的实参变量,必须赋初始值

out(C# 参考)

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

关键字。

例如:

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 参数,则无法重载这两个方法。例如,从编译的角度来看,以下代码中的两个方法是完全相同的,因此将不会编译以下代码:

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 参数,而另一个方法不采用这两类参数,则可以进行重载,如下所示:

class RefOutOverloadExample

{

    public void SampleMethod(int i) { }

    public void SampleMethod(out int i) { }

}

原文:

面试题

对于编译后的程序而言,它们之间没有任何区别,也就是说它们只有语法区别。

 

 

使用ref的时候要传入相应方法的实参变量,必须赋值。而out在调用的时候只用声明,但是在方法内部,修饰了out形参必须赋值。

通过out的方式实现:

 

加上ref修饰形参:

根据值类型和引用类型的特点,值类型是赋值,是复制传递的是栈上存储的具体值信息,如图实参变量"a"将100赋值给方法形参"num"变量。那么值类型的改变只会影响值的本身,形参的改变没有形象到变量"a"。

观察一:

 

 

 

 

 

  static void Main(string[] args)
        {

            int a ;
            changeNum(out a);
            Console.WriteLine(a); //结果为101
        }

        static stringchangeNum(out int num)
        {
            num = 100;
            num  ;    
             return "ok";
        }

 

当调用一个方法时,传入的参数是一个值类型,那么需要方法将这个传入的值类型的变量值改变受到影响,我们可以使用ref 关键字进行处理实现。

 


 

美高梅4858官方网站 3

从语法规则上来讲,一个方法只能有一个返回值,如果return多个值简直是天方夜谭,如图:

1.用了ref关键的方法,必须在参数列表上加上ref关键字,在调用该方法的时候也要加上ref关键字。

 

2.方法参数列表上修饰了out关键字的变量,必须在方法体赋初始值,对于方法调用提供的实参变量可以不需要赋值。

通过ref关键字,此时传递变量a的时候,实参把引用传给了形参,那么说明了这两个变量将指向同一个引用地址,变量num在方法中的改变会影响到变量a

本文由分分快三计划发布,转载请注明来源

关键词: C# C#基础 ref和out ref与out之间