代码改变世界

从设计意图看OUT参数和REF参数的区别与联系

2011-10-12 17:37  Shawn.Cheng  阅读(261)  评论(0编辑  收藏  举报

 

学习并使用C#已经好久了,最近在看.NET框架程序设计,又对这些基础概念进行了一次回顾与加深。高手毕竟是高手,同样一个问题,虽然答案差不多,但是回答问题所站的角度却不同。

下边是我对两者区别与联系的体会。

Out参数和ref参数的基本用法这里不再详谈。

要说他们的区别与联系,我们就必须说明二者的设计意图分别是什么。前者out,顾名思义,是为了输出,而后者ref是引用,是为了传入参数,二者设计意图不同那么使用的时候,就需要按照原本的意图去使用。由于意图不同,那么使用的时候也就有所差别,前者为了输出,那么就不必要保证在传入参数之前进行初始化,而后者由于目地是为了出入参数后使用,那么就必须保证传入参数之前进行初始化操作。这里,就从编译器这一块保证我们程序是正确的。

从clr角度来讲,二者是无差别的,行为是相同的。因为二者本质上讲都是传入了原来参数的地址,然后,直接操作该地址指向的空间。也就是说,假设原来的参数值值类型的,那么改值类型在堆栈上申明,初始化之后,会将该地址传给那个函数,然后,在该函数中,直接使用该地址对 对应空间进行操作。

我们在调用的时候,也需要指明类型,这样我们能够很明确的知道调用该参数的意图是什么(据说这也是C#设计者的意图)。

我们也可以通过out和ref来重载方法,但是仅通过out和ref来区分是不合法的,因为他们经过jit编译后代码是相同的。

Class Point

         Staticvoid Add(Point p){}

         Staticvoid Add(ref p){}

//      Staticvoid Add(out p){}//和上边的只能选其一

 

还有一个问题是,使用引用传入参数时,必须保证传入的参数类型的必须完全一致,比如说,

String str=”hello”;

GetObj(str);

 

Void GetObj(out object ob)

         Ob=newString(“000”);

是无法通过编译的,这样,确保了类型安全,防止因为传入参数传出后类型发生变化,之后的方法调用失败。

 

以前写代码的时候,常常使用ref去对参数进行改变,然后获取使用,沿袭了C++的思想,现在看来,应该严格按照原本的语言意图去写,这样,才能使代码更加健壮。