C#中ref和out关键字的应用以及区别。


之前要学习一下C#的更深入的东西时,看到了ref和out的概念。看了一些教程之后,感觉还是明白了用法,但是不知道语言的深层含义。所以整理了一番,写成博客,帮助大家可以理解,并且于我,也是一个重新整理思路的过程。
首先国际惯例,要了解一个东西的时候,首先明白它是什么,然后明白它能做什么,最后要知道为什么。

ref

ref的定义

ref:MSDN的定义为:“The ref keyword indicates a value that is passed by reference.”就是通过引用来传递参数。ref也是Reference的缩写。了解了定义之后,ref怎么用呢?首先我们要明白值类型和引用类型的概念。这里的ref基本上就是服务于值类型的。

ref 的使用

//不使用 ref;
void Method(int myRefInt)
{
    myRefInt += 66;
}

int number = 1;
Method(number);
Console.WriteLine(number);
**//输出 : 1;**
//使用ref
void Method(ref int myRefInt)
{
    myRefInt += 66;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);

**//输出:67**

看到这里想必已经明白了:

  • 不使用ref的时候,函数收到的值是1,然后在Method(int myRefInt)方法中,局部变量myRefInt做了累加之后,在方法执行完成之后就已经销毁了。number的值还是1。
  • 使用ref的时候,函数Method(ref int myRefInt)值收到的是number的地址,函数中执行的myRefInt+=66;此时相当于number+=66;直接修改了number地址的值。
    那就可以等处结论了:ref是通过给方法传递值类型的参数,直接操作同一个变量的关键字。

out

out的定义:来自MSDN

  • As a parameter modifier, which lets you pass an argument to a method by reference rather than by value./“out”作为一个参数修饰符,允许您通过引用而不是通过值将参数传递给方法。
  • In generic type parameter declarations for interfaces and delegates, which specifies that a type parameter is covariant./在接口和委托的泛型类型参数声明中,它指定类型参数是协变的。
    今天的语境下,我们只讨论第一种作为引用传递参数的定义。

out的用法

int number;

Method(number);

void Method(int myRefInt)
{
    myRefInt = 66;
}

Console.WriteLine(number);
//输出:0
int number;

Method(out number);

void Method(out int myRefInt)
{
    myRefInt = 66;
}

Console.WriteLine(number);
//输出:66

从上述out用法的表现来看,out和ref其实都可以允许通过引用来传递参数。那么问题来了既然ref 、out的作用看起来一样,为什么还定义了两个关键字呢?

ref和out的区别

Stack Overflow的解释:

在这里插入图片描述
意思就是:当你在使用ref传递参数的时候,ref修饰的参数必须要有值,但是out可以使用一个未赋值的变量作为参数传递。下面我也用代码做了验证。

 class RefAndOut
    {
        public static void OutDouble(out int outInt)
        {
            outInt = 2;
            Console.WriteLine("outInt is:"+outInt);
        }
        public static void RefDouble(ref int parInt)
        {
            parInt *= 2;
            Console.WriteLine("refInt is:"+parInt);
            Console.ReadKey();
        }
        public static void NormalDouble(int IntPar)
        {
            IntPar = 1;
            IntPar *= 2;
            Console.WriteLine("normalInt is:" + IntPar);
            Console.ReadKey();
        }
        static void Main(string[] args)
        {
            int refInt;
            int outInt;
            int normalInt;
            OutDouble(out outInt);
            RefDouble(ref refInt);
            NormalDouble(normalInt);
        }
    }

这段代码在两处地方有错误:即在使用ref,和不使用修饰符的时候,必须要传递一个有值的参数。所以你看,ref和out几乎就只有一个区别,那就是out可以使用未赋值的变量。
在这里插入图片描述
但是此处还有一个未解的地方,就是为什么Out不需要赋值呢?这也是这篇博客拖了一周的原因。。今天大概能解释了。我们看下图,不管有没有对静态变量outInt赋值,只要出使用out修饰符,就必须对out修饰的参数outIntPar赋值。
所以out应该是在方法内部做了分配地址的操作,然后把地址赋给外部的变量。但是ref的话是直接传递外部地址进方法。OK至此已经解释清楚ref和out的区别了。
如果有错误的地方还请指出一同讨论。
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章