C#中ref和out關鍵字的應用以及區別。


之前要學習一下C#的更深入的東西時,看到了ref和out的概念。看了一些教程之後,感覺還是明白了用法,但是不知道語言的深層含義。所以整理了一番,寫成博客,幫助大家可以理解,並且於我,也是一個重新整理思路的過程。
首先國際慣例,要了解一個東西的時候,首先明白它是什麼,然後明白它能做什麼,最後要知道爲什麼。

ref

ref的定義

ref:MSDN的定義爲:“The ref keyword indicates a value that is passed by reference.”就是通過引用來傳遞參數。ref也是Reference的縮寫。瞭解了定義之後,ref怎麼用呢?首先我們要明白值類型和引用類型的概念。這裏的ref基本上就是服務於值類型的。

ref 的使用

//不使用 ref;
void Method(int myRefInt)
{
    myRefInt += 66;
}

int number = 1;
Method(number);
Console.WriteLine(number);
**//輸出 : 1;**
//使用ref
void Method(ref int myRefInt)
{
    myRefInt += 66;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);

**//輸出:67**

看到這裏想必已經明白了:

  • 不使用ref的時候,函數收到的值是1,然後在Method(int myRefInt)方法中,局部變量myRefInt做了累加之後,在方法執行完成之後就已經銷燬了。number的值還是1。
  • 使用ref的時候,函數Method(ref int myRefInt)值收到的是number的地址,函數中執行的myRefInt+=66;此時相當於number+=66;直接修改了number地址的值。
    那就可以等處結論了:ref是通過給方法傳遞值類型的參數,直接操作同一個變量的關鍵字。

out

out的定義:來自MSDN

  • As a parameter modifier, which lets you pass an argument to a method by reference rather than by value./“out”作爲一個參數修飾符,允許您通過引用而不是通過值將參數傳遞給方法。
  • In generic type parameter declarations for interfaces and delegates, which specifies that a type parameter is covariant./在接口和委託的泛型類型參數聲明中,它指定類型參數是協變的。
    今天的語境下,我們只討論第一種作爲引用傳遞參數的定義。

out的用法

int number;

Method(number);

void Method(int myRefInt)
{
    myRefInt = 66;
}

Console.WriteLine(number);
//輸出:0
int number;

Method(out number);

void Method(out int myRefInt)
{
    myRefInt = 66;
}

Console.WriteLine(number);
//輸出:66

從上述out用法的表現來看,out和ref其實都可以允許通過引用來傳遞參數。那麼問題來了既然ref 、out的作用看起來一樣,爲什麼還定義了兩個關鍵字呢?

ref和out的區別

Stack Overflow的解釋:

在這裏插入圖片描述
意思就是:當你在使用ref傳遞參數的時候,ref修飾的參數必須要有值,但是out可以使用一個未賦值的變量作爲參數傳遞。下面我也用代碼做了驗證。

 class RefAndOut
    {
        public static void OutDouble(out int outInt)
        {
            outInt = 2;
            Console.WriteLine("outInt is:"+outInt);
        }
        public static void RefDouble(ref int parInt)
        {
            parInt *= 2;
            Console.WriteLine("refInt is:"+parInt);
            Console.ReadKey();
        }
        public static void NormalDouble(int IntPar)
        {
            IntPar = 1;
            IntPar *= 2;
            Console.WriteLine("normalInt is:" + IntPar);
            Console.ReadKey();
        }
        static void Main(string[] args)
        {
            int refInt;
            int outInt;
            int normalInt;
            OutDouble(out outInt);
            RefDouble(ref refInt);
            NormalDouble(normalInt);
        }
    }

這段代碼在兩處地方有錯誤:即在使用ref,和不使用修飾符的時候,必須要傳遞一個有值的參數。所以你看,ref和out幾乎就只有一個區別,那就是out可以使用未賦值的變量。
在這裏插入圖片描述
但是此處還有一個未解的地方,就是爲什麼Out不需要賦值呢?這也是這篇博客拖了一週的原因。。今天大概能解釋了。我們看下圖,不管有沒有對靜態變量outInt賦值,只要出使用out修飾符,就必須對out修飾的參數outIntPar賦值。
所以out應該是在方法內部做了分配地址的操作,然後把地址賦給外部的變量。但是ref的話是直接傳遞外部地址進方法。OK至此已經解釋清楚ref和out的區別了。
如果有錯誤的地方還請指出一同討論。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章