从设计意图看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++的思想,现在看来,应该严格按照原本的语言意图去写,这样,才能使代码更加健壮。