26C#中ref、out、in的區別與使用


  • ref 修飾符,指定參數由引用傳遞,可以由調用方法讀取或寫入。
  • out 修飾符,指定參數由引用傳遞,必須由調用方法寫入。
  • in 修飾符,指定參數由引用傳遞,可以由調用方法讀取,但不可以寫入。

遂碼之,首先是in:

image
可以看到,不能對in參數賦值,可見只能讀,不能寫

再來out:

image
可以看到,out參數不能讀,只能寫,就算在main中初始化,也是當做未賦值來看待

最后再來ref:

image
ref沒有任何報錯,可見是可讀可寫的,了解,還有就是ref參數必須初始化,不然會報錯,in也是。

ref、out、in參數不能當做重載的依據

image

總結

ref、out、in都是將參數按引用來傳遞,我們普通做法什么都不加是用的值傳遞,這在內存分配上是有差異的。

ref:可讀可寫(可進可出)

out:只能寫不能讀(只出不進)

in:只能讀不能寫(只進不出)


詳細理解

In:過程不會改寫In的內容
out:傳入的值不會被過程所讀取,但過程可以寫
ref:傳入的值,過程會讀,也會寫

ref

通常我們向方法中傳遞的是值.方法獲得的是這些值的一個拷貝,然后使用這些拷貝,當方法運行完畢后,這些拷貝將被丟棄,而原來的值不將受到影響.此外我們還有其他向方法傳遞參數的形式,引用(ref)和輸出(out).

有時,我們需要改變原來變量中的值,這時,我們可以向方法傳遞變量的引用,而不是變量的值.引用是一個變量,他可以訪問原來變量的值,修改引用將修改原來變量的值.變量的值存儲在內存中,可以創建一個引用,他指向變量在內存中的位置.當引用被修改時,修改的是內存中的值,因此變量的值可以將被修改.當我們調用一個含有引用參數的方法時,方法中的參數將指向被傳遞給方法的相應變量,因此,我們會明白,為什么當修改參數變量的修改也將導致原來變量的值.

創建參數按引用傳遞的方法,需使用關鍵字ref.例;

using System;
class gump
{
    public double square(ref double x)
    {
        x=x*x;
        return x;
    }
}

class TestApp
{
    public static void Main()
    {
        gump doit=new gump();

        double a=3;
        double b=0;

        Console.WriteLine(\"Before square->a={0},b={1}\",a,b);

            b=doit.square(ref a);
        Console.WriteLine(\"After square->a={0},b={1}\",a,b);
    }
}

通過測試,我們發現,a的值已經被修改為9了.

out

通過指定返回類型,可以從方法返回一個值,有時候(也許還沒遇到,但是我們應該有這么個方法),需要返回多個值,雖然我們可以使用ref來完成,但是C#專門提供了一個屬性類型,關鍵字為out.介紹完后,我們將說明ref和out的區別.

通過使用out關鍵字,我們改變了三個變量的值,也就是說out是從方法中傳出值.

using System;
class gump
{
    public void math_routines(double x,out double half,out double squared,out double cubed)
//可以是:public void math_routines(ref double x,out double half,out double squared,out double cubed)
//但是,不可以這樣:public void math_routines(out double x,out double half,out double squared,
//out double cubed),對本例來說,因為輸出的值要靠x賦值,所以x不能再為輸出值
    {
        half=x/2;
        squared=x*x;
        cubed=x*x*x;
    }
}

class TestApp
{
    public static void Main()
    {
        gump doit=new gump();

        double x1=600;
        double half1=0;
        double squared1=0;
        double cubed1=0;
        [Page]
        /*
        double x1=600;
        double half1;
        double squared1;
        double cubed1;
        */

        Console.WriteLine(\"Before method->x1={0}\",x1);
        Console.WriteLine(\"half1={0}\",half1);    Console.WriteLine(\"squared1={0}\",squared1);
        Console.WriteLine(\"cubed1={0}\",cubed1);



        doit.math_rountines(x1,out half1,out squared1,out cubed1);

        Console.WriteLine(\"After method->x1={0}\",x1);
            Console.WriteLine(\"half1={0}\",half1);
            Console.WriteLine(\"squared1={0}\",squared1);
            Console.WriteLine(\"cubed1={0}\",cubed1);
    }
}

我們發現,ref和out似乎可以實現相同的功能.因為都可以改變傳遞到方法中的變量的值.但是,二者本質本質的區別就是,ref是傳入值,out是傳出值.在含有out關鍵字的方法中,變量必須由方法參數中不含out(可以是ref)的變量賦值或者由全局(即方法可以使用的該方法外部變量)變量賦值,out的宗旨是保證每一個傳出變量都必須被賦值.

上面代碼中被/**/注釋掉的部分,可以直接使用.也就是說,在調用方法前可以不初始化變量.但是"x1"是要賦值的,否則要報錯.而ref參數,在傳遞給方法時,就已經是還有值的了,所以ref側重修改.out側重輸出(返回值).


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM