C#中的ref以及out内解

说明问题之前,我们先来看一段代码:

    class Program

    {

        static void Main(string[] args)

        {

            int a = 1, b = 2;

            swap(a, b);

            Console.WriteLine("a={0},b={1}", a, b);

        }

 

        static void swap(int a, int b)

        {

            int temp = a;

            a = b;

            b = temp;           

        }

    }

结果依然是a=1,b=2,swap方法并没有将交换后的结果返回。

这是因为swap方法的形参是按传值形式被调用的。当swap方法准备执行时,形参b和a会被各自赋值(即2和1),然后压入堆栈中,swap方法执行完成后,形参a和b弹栈。这个过程中,Main中的a和b的值始终没有发生变化,所以输出时,依然是原始值。

 

在java中,我们只能通过return将修改后的值进行返回。但是在C#中,提供了更多的手段,可以不通过return而直接在调用方法中将值修改并影响原来的变量,这就是ref或者out关键字。

     class Program

    {

        static void Main(string[] args)

        {

            int a = 1, b = 2;

            swap(ref a, ref b);

            Console.WriteLine("a={0},b={1}", a, b);

        }

 

        static void swap(ref int a, ref int b)

        {

            int temp = a;

            a = b;

            b = temp;

           

        }

    }

 

这里可以看到,a和b的值已经发生了交换。

 那么ref和out的区别在哪里呢?

  1. ref的参数在调用之前必须先初始化,而out的不需要;
  2. 在调用方法内,ref的形参可以直接使用,而out的必须先赋值再使用。

比如下面两种错误:

错误一:

其中display方法:

 

错误二:

总结:

  1. ref和out提供了按引用传递的功能(这里的“引用”并不是指“引用类型”的引用),我们可以在调用方法内部对传递进来的参数进行修改;
  2. ref的使用场景:调用方法对参数param进行处理时,依赖param的初始值。比如,方法内部进行param++操作时;
  3. out的使用场景:调用方法对参数param进行处理时,不依赖param的初始值。比如,方法内部进行param=40这样的赋值操作时。

接下来看一看IL是怎么对待按值或者按引用传递的参数。比如这一段C#代码:

classClass
{
   
void Method(Class @class) { }
   
void Method(ref Class @class) { }
   
//void Method(out Class @class) { }
}

这一段代码是可以正常通过编译的,但是取消注释就不行了,因为IL是不区分ref和out的。

也正是因为这一种重载的可能性,所以在调用方也必须写明ref或out,不然编译器没法区分调用的是哪一个重载版本。

Class类的IL是这样的:

.classprivate auto ansi beforefieldinit CsConsole.Class
   
extends[mscorlib]System.Object
{
    //Methods
   
.method private hidebysig static
       
void Method (
           
class CsConsole.Class'class'
       
) cil managed
    {
        //Method begins at RVA 0x20b4
       
// Code size 1 (0x1)
       
.maxstack 8

IL_0000: ret
   
} //end of method Class::Method

.method private hidebysig static
       
void Method (
           
class CsConsole.Class&

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值