NET|Ref 和out 的区别和联系

首先看一下msdn上是怎么描述的。

Therefkeyword causes an argument to be passed byreference, not by value. The effect of passing by reference is that any changeto the parameter in the called method is reflected in the calling method. Forexample, if the caller passes a local variable expression or an array elementaccess expression, and the called method replaces the object to which the refparameter refers, then the caller’s local variable or the array element nowrefer to the new object.

我尝试翻译一下。ref关键字是引用传递,区别于按值传递。引用传递的作用是,调用方法中的对参数的任何更改,在函数执行完成后都会影响到该参数。例如,如果调用方传递一个局部变量表达式或数组元素访问表达式,调用的方法将替换引用参数指向的对象,则调用方的本地变量或数组元素将引用新对象。

Theoutkeyword causes arguments to be passed byreference. It is like therefkeyword,except thatrefrequires that the variable be initializedbefore it is passed. To use anoutparameter, both the method definition and thecalling method must explicitly use theoutkeyword. For example:

out关键字也是引用传递参数。它就像REF关键字,除了REF要求变量在它被传递之前被初始化。若要使用out参数,方法定义和调用方法必须显式使用out关键字。

简单概括,在功能作用上,ref和out都是引用传递,实现的功能,官方的说法是为了保留函数执行过程中对变量的改变能够得以保留。我的个人理解是为了解决多个返回值的情况。但一个的基本的共识是这两个关键字是基本可以相互替代的。那么为什么还有这两种关键字还会同时存在呢。下面我们来简单分析一下。

用一个简单的例子来实验一下。我们需要在一个函数中完成两个变量x和y的求和和求差

NET|Ref 和out 的区别和联系_第1张图片

首先我们来看一下,a和b作为普通参数传递,此时,函数执行完成后,a和b的值仍旧是0,函数内部对他的赋值丢失了。

NET|Ref 和out 的区别和联系_第2张图片

然后我们使用ref关键字来试一下,会发现使用ref关键字的时候,我们在函数内部对他的赋值,在函数执行完成后并未丢失

同样的,使用out关键字的之后,函数内部的结果在函数执行完成后,仍得以保留。

NET|Ref 和out 的区别和联系_第3张图片
out关键字


NET|Ref 和out 的区别和联系_第4张图片
ref关键字

以上不难看出,ref和out关键字都实现了引用传递,完成了多个返回的功能。

我们把对a和b的赋值去掉,就可以看到差别了。

NET|Ref 和out 的区别和联系_第5张图片
out模式下去掉变量初始化
NET|Ref 和out 的区别和联系_第6张图片
ref模式下去掉初始化
NET|Ref 和out 的区别和联系_第7张图片
不使用关键字 去掉变量初始化

去掉a和b的赋值,对out是没影响的。Ref和普通传值都出出现使用未赋值变量的报错。

普通传值很好理解,变量在使用前必须初始化。而ref的第一要素也是使用前必须初始化,而out是不需要的。

然后我们来解决第二个问题,既生瑜何生亮,既有ref何生out,看什么时候ref和out在那些情况下不能互换。

需求是动态的,问题也是,刚才的问题我们稍微改变一下。

需要在函数N中实现,x>y求和求差

NET|Ref 和out 的区别和联系_第8张图片
x>y 使用ref out求值

对比上图,我们会发现,我们加了if条件,改造函数之后,out编译不过了。

原因就在于out关键字的变量在使用前可能没有初始化,要求必须在函数内部被赋值。也就是条件分支必须完全覆盖。刚才那个地方,我们稍微改造一下即可。

NET|Ref 和out 的区别和联系_第9张图片
out模式下增加赋值分值

以下这段话,纯属个人理解,ref倾向于传递,而out倾向于返回,因此无论是传递还是返回,过程中被改变,结果也会被改变。区别在于,传递的过程可能被改变也可以不被改变,而返回是必须返回一个固定的值。如果比较难懂,可忽略此段。

我们再来模拟一个问题

现有变量x,y,a,b,如果x>y则a+1,b-1反之b+1,a-1。我们会发现out很难写。而如果存在多组x,y的情况,out更是无法实现。

那么out的常用使用场景有哪些呢。我用的最多就是系统函数TryParse。我们定义了一个变量,无论使用convert还是parse都有可能会报错,但tryparse在内部处理了这个问题。即使转换异常,函数也会在内部帮我们把变量初始化成固定值。

你可能感兴趣的:(NET|Ref 和out 的区别和联系)