深入剖析引用參數Ref和Out

作者: Wu.Country@俠緣  來源: 博客園  發布時間: 2009-02-27 13:58  閱讀: 4172 次  推薦: 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
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()