深入剖析引用参数Ref和Out

学过C/C++的人,对C#的关键字Ref和Out应该都很好理解。它们都提供了一种可以在被调用函数内修改传递的参数的值的方法。因为这一功能很类似C/C++的指针。对于没学过C/C++的,也应该可以明白这两个参数的作用。

虽然Ref和Out都提供了修改参数值的方法,但它们还是有一点点小的区别。
1、Ref在作为参数调用函数之前,变量一定要赋值,否则会得到一个常规编译错误:使用了未赋值的变量。
2、在被调用函数内,以Ref引入的参数在返回前不必为它赋值。
3、Out在作为参数调用函数之前,变量可以不被赋值。
4、在被调用函数内,以Out引入的参数在返回前一定要至少赋值一次。

其实本质上讲,Ref更适合理解为给被调用函数传递了一个与原参考同地址的变量。而Out则可以理解为在调用函数前,先给变量找个地方,让被调用函数在给定地点放一个值。

看上去很简单不是吗?确实如此,这里是一个例子:

namespace StudyAndTest

{

    /**//// 

    /// Summary description for Class1.

    /// 

    class Class1

    {

        /**//// 

        /// The main entry point for the application.

        /// 

        [STAThread]

        static void Main(string[] args) 

        {

            int m_temp        =0;    //Must be assigned to before call any mothed with the

variable by reference.

            
Console.WriteLine("Int data befor change:{0}",m_temp);

            ChangeData1(ref m_temp);

            Console.WriteLine("Int data after change:{0}",m_temp);

            ChangeData2(out m_temp);

            Console.WriteLine("Int data after change:{0}",m_temp);

        }

static void ChangeData1(ref int i_ref)

        {

            Console.WriteLine("Int data in ChangeData1:{0}",i_ref);

            i_ref    = 1;

        }

static void ChangeData2(out int i_ref)

        {

            //Console.WriteLine("Int data in ChangeData2:{0}",i_ref);    //Error in building, use of unassigned local variable i_ref

            i_ref    = 2;    //The out parament i_ref must be assigned to before control leaves the

 
current mothod.

        }

    }

}

然而C#毕竟是与C/C++有着不同之处的。这就是在C#内,所有的变量被分为两类:值类型和引用类型。
那么我们就会有这样的问题:将Ref和Out分别应用于引用类型和值类型的变量上,会是什么样的结果呢?

对于应用于值类型数据的情况,上面的例子已经完全讨论过了,就是完全遵守上面的四句话。而对于引用类型数据,有一个很有趣的问题,就是默认情况下(不带Ref也不带Out)它是以Ref情况而调用函数,即上面的四句话仍然满足。

看这样的一个例子:

namespace StudyAndTest

{

    /**//// 

    /// Summary description for Class1.

    /// 

    class Class1

    {

        /**//// 

        /// The main entry point for the application.

        /// 

        [STAThread]

        static void Main(string[] args) 

        {

            TempClass m_class1    = new TempClass();

            m_class1.m_member    = 0;

            Console.WriteLine("i_obj data before changeData3 :{0}",m_class1.m_member);

            ChangeData3(m_class1);

            Console.WriteLine("i_obj data after changeData3 :{0}",m_class1.m_member);

}

        static void ChangeData3(TempClass i_obj)

        {

            i_obj.m_member    = 3;

//            Console.WriteLine("i_obj data in ChangeData3:{0}",i_obj.m_member);

        }

    }

class TempClass

    {

        public int m_member;

    }

}

这让人感觉就是Ref,确实如此,默认就是在以Ref为引用类型在调用函数,所以还是要注意以下问题:
引用类型数据一定要初始化。而至于引用类型自己初始化的问题,就交给该类型自己了。如上面的问题,m_member在没有赋值前,一样可以编译的,但运行一定就不对了(但有默认值),这是因为TempClass里没有构造函数。在被调用函数内,一样的使用参数,而且所有对引用参数的改变都影响到函数外。这是默认的情况。

继续>>下一页[第1页][第2页]

时间: 2024-08-03 11:29:58

深入剖析引用参数Ref和Out的相关文章

输出参数out和引用参数ref区别

使用ref的一段代码 using System; class M { public void F(ref int i) { i=3; } } class Test { int i=0; //要作为引用参数传递的变量必须明确赋值 static void Main() { //不能把int i=0;放在这里赋值,会报错说Test不包含i定义. Test t=new Test(); Console.WriteLine("the value of i is:{0}",t.i); M mm=ne

C#的引用参数和值参数

引用参数和值参数 在前面的函数学习中,所有函数的参数都是有值参数:在使用参数的时候把一个值传递给函数使用的一个变量.在函数中对此变量的任何修改都不会影响函数调用中指定的参数.还是举例说明比较好: static void doDouble(double mynum) { mynum *= 2; Console.WriteLine("mynum in 函数中doDouble{0}", mynum); } static void Main(string[] args) { Console.W

未引用参数,添加任务栏命令及其它

我看到过一些 C++ 代码针对没有使用过的参数用 UNREFERENCED_PARAMETER,例如: int SomeFunction(int arg1, int arg2) { UNREFERENCED_PARAMETER(arg2) ... } 我还看到过这样的代码: int SomeFunction(int arg1, int /* arg2 */) { ... } 你能解释它们的差别吗?哪一种用法更好? Judy McGeough 是啊!为什么呢?让我们从 UNREFERENCED_P

引用参数和传值参数的区别深入解析

以下是对引用参数和传值参数的区别进行了详细的分析介绍,需要的朋友可以过来参考下   1. 我们都知道,普通的传值参数是由行参传给实参: 编译器在函数内部为每一个参数产生一个临时变量,将每一个参数压入栈(stack)中,将实参的数值保存到临时变量中. 所以才有在低端8位机中,对参数的数量有比较严格的限制,因为栈的深度非常有限:当然,在通用机上也有同样的问题,参数过多不合适,但通用机的栈的深度比低端机大多了: 2. 引用做参数传递的是变量的地址: 实质上传递的是变量的指针: 引用作为参数的好处是减少

数据结构-抽象数据类型的定义中的“引用参数”怎么理解

问题描述 抽象数据类型的定义中的"引用参数"怎么理解 InitTriplet(&Tv1v2v3) 初始条件: 操作结果:用e值取代三元组T的第i个元素 DestroyTriplet(&T) 初始条件:三元组T已经存在. 操作结果:销毁三元组T. Get(Ti&e) 初始条件:三元组T已经存在,1<=i<=3 操作结果:用e返回三元组T的第i个元素. Put(&Tie) 初始条件:三元组T已经存在,1<=i<=3 操作结果:用e值取

myeclipse-求解!List总被提示要引用参数用@SuppressWarnings(&amp;amp;quot;unchecked&amp;amp;quot;)会影响程序运行么

问题描述 求解!List总被提示要引用参数用@SuppressWarnings("unchecked")会影响程序运行么 List list = sn.getSiteInfo(); String sitename = list.get(0).toString(); String method=request.getParameter(""method""); String stime=""2"";Strin

《从缺陷中学习C/C++》——6.14 正确使用引用参数和引用返回值

6.14 正确使用引用参数和引用返回值 从缺陷中学习C/C++代码示例 int &add(int n, int m) { n = n + m; return n; } int main() { int i = 10; int b = add(i, 1); cout << b << endl; return 0; } 现象&后果预期的输出结果是11,但实际输出的结果不确定. Bug分析add函数是一个函数引用,而add函数的返回值是形参n,形参是函数内的局部变量,函数

c++-C++里面引用参数的问题。

问题描述 C++里面引用参数的问题. 刚学C++,对引用不是很清楚.能否用这个题举例一下,谢谢 解决方案 方法1 int CalPfh1(int x, int y) { return x * x + y * y; } 方法2 void CalPfh2(int x, int y, int & z) { z = x * x + y * y; } 调用 cout << CalPfh1(3, 2) << endl; int z = 0; CalPfh2(3, 2, z); cout

C# 方法参数 ref 详述

其实这个问题很容易理解,首先在C#中传递方法参数缺省是"值拷贝"模式,也就是说对于值类型(ValueType)变量直接拷贝一份,而对于引用类型则拷贝一个指向同一对象的引用副本传递给方法,因此即使不使用ref关键字,我们也可以在方法内部改变该引用所指向对象的内部状态,但是某些时候我们需要在方法内部创建一个新的对象实例,并使得原有引用指向这个新的对象.那么问题就来了,由于现在存在两个引用,我们改变的只是传递到方法的引用副本,而该副本在超出方法作用域后既失去作用,而原有的引用依然指向原有对象