您的位置:知识库 » .NET技术

深入剖析引用参数Ref和Out

作者: Wu.Country@侠缘  来源: 博客园  发布时间: 2009-02-27 13:58  阅读: 4390 次  推荐: 0   原文链接   [收藏]  
摘要:Ref和Out 解释
[1] 深入剖析引用参数Ref和Out
[2] 深入剖析引用参数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页]
0
0
标签:CLR

.NET技术热门文章

    .NET技术最新文章

      最新新闻

        热门新闻