日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

C# ref和out的區(qū)別

 zww_blog 2013-09-12

問(wèn)題:為什么c#中要有ref和out?(而java中沒(méi)有)

首先:兩者都是按地址傳遞的,使用后都將改變?cè)瓉?lái)參數(shù)的數(shù)值。

其次:ref可以把參數(shù)的數(shù)值傳遞進(jìn)函數(shù),但是out是要把參數(shù)清空,就是說(shuō)你無(wú)法把一個(gè)數(shù)值從out傳遞進(jìn)去的,out進(jìn)去后,參數(shù)的數(shù)值為空,所以你必須初始化一次。這個(gè)就是兩個(gè)的區(qū)別,或者說(shuō)就像有的網(wǎng)友說(shuō)的,ref是有進(jìn)有出,out是只出不進(jìn)。


需求假設(shè):現(xiàn)需要通過(guò)一個(gè)叫Swap的方法交換a,b兩個(gè)變量的值。交換前a=1,b=2,斷言:交換后a=2,b=1。

現(xiàn)編碼如下:

class Program
   {
       static void Main(string[] args)
       {
           int a = 1;
           int b = 2;
            Console.WriteLine("交換前\ta={0}\tb={1}\t",a,b);
           Swap(a,b);
            Console.WriteLine("交換后\ta={0}\tb={1}\t",a,b);
            Console.Read();
       }
       //交換a,b兩個(gè)變量的值
       private static void Swap(int a,int b)
       {
           int temp = a;
           a = b;         
           b = temp;
           Console.WriteLine("方法內(nèi)\ta={0}\tb={1}\t",a,b);
        }
    }

運(yùn)行結(jié)果:

              交換前 a = 1    b = 2

               方法內(nèi) a = 2    b = 1

              交換后 a = 1     b = 2

斷言失敗,并未達(dá)到我們的需求!

原因分析:int類型為值類型,它存在于線程的堆棧中。當(dāng)調(diào)用Swap(a,b)方法時(shí),相當(dāng)于把a(bǔ),b的值(即1,2)拷貝一份,然后在方法內(nèi)交換這兩個(gè)值。交換完后,a還是原來(lái)的a,b還是原來(lái)的b。這就是C#中按值傳遞的原理,傳遞的是變量所對(duì)應(yīng)數(shù)據(jù)的一個(gè)拷貝,而非引用。

解決方案:因此,C#中提出了ref 和out兩個(gè)關(guān)鍵字。

修改代碼如下即可實(shí)現(xiàn)我們想要的結(jié)果:

class Program
{
       static void Main(string[] args)
      {
            int a = 1;
           int b = 2;
            Console.WriteLine("交換前\ta={0}\tb={1}\t",a,b);
            Swap(ref a,ref b);
            Console.WriteLine("交換后\ta={0}\tb={1}\t",a,b);
            Console.Read();
        }
       //交換a,b兩個(gè)變量的值
        private static void Swap(ref int a, ref int b)
        {
            int temp = a;
            a = b;
            b = temp;
            Console.WriteLine("方法內(nèi)\ta={0}\tb={1}\t",a,b);
       }
    }

同理用out同樣可以實(shí)現(xiàn)我們的需求。

下面談?wù)剅ef和out到底有什么區(qū)別:

1關(guān)于重載

原則:有out|ref關(guān)鍵字的方法可以與無(wú)out和ref關(guān)鍵字的方法構(gòu)成重載;但如想在out和ref間重載,編譯器將提示:不能定義僅在ref和out的上的方法重載

ref out 關(guān)鍵字在運(yùn)行時(shí)的處理方式不同,但在編譯時(shí)的處理方式相同。因此,如果一個(gè)方法采用 ref 參數(shù),而另一個(gè)方法采用 out 參數(shù),則無(wú)法重載這兩個(gè)方法。例如,從編譯的角度來(lái)看,以下代碼中的兩個(gè)方法是完全相同的,因此將不會(huì)編譯以下代碼:

class CS0663_Example

{

    // Compiler error CS0663: "Cannot define overloaded

    // methods that differ only on ref and out".

    public void SampleMethod(out int i) { }

    public void SampleMethod(ref int i) { }

}

 

但是,如果一個(gè)方法采用 ref out 參數(shù),而另一個(gè)方法不采用這兩類參數(shù),則可以進(jìn)行重載,如下所示:

class RefOutOverloadExample

{

    public void SampleMethod(int i) { }

    public void SampleMethod(out int i) { }

}

2 關(guān)于調(diào)用前初始值

   原則:ref作為參數(shù)的函數(shù)在調(diào)用前,實(shí)參必須賦初始值。否則編譯器將提示:使用了未賦值的局部變量;

          out作為參數(shù)的函數(shù)在調(diào)用前,實(shí)參可以不賦初始值。

3 關(guān)于在函數(shù)內(nèi),引入的參數(shù)初始值問(wèn)題

   原則:在被調(diào)用函數(shù)內(nèi),out引入的參數(shù)在返回前至少賦值一次,否則編譯器將提示:使用了未賦值的out參數(shù);

           在被調(diào)用函數(shù)內(nèi),ref引入的參數(shù)在返回前不必為其賦初值。

總結(jié):C#中的ref和out提供了值類型按引用進(jìn)行傳遞的解決方案,當(dāng)然引用類型也可以用ref和out修飾,但這樣已經(jīng)失去了意義。因?yàn)橐脭?shù)據(jù)類型本來(lái)就是傳遞的引用本身而非值的拷貝。ref和out關(guān)鍵字將告訴編譯器,現(xiàn)在傳遞的是參數(shù)的地址而不是參數(shù)本身,這和引用類型默認(rèn)的傳遞方式是一樣的。同時(shí),編譯器不允許out和ref之間構(gòu)成重載,又充分說(shuō)明out和ref的區(qū)別僅是編譯器角度的,他們生成的IL代碼是一樣的。有人或許疑問(wèn),和我剛開始學(xué)習(xí)的時(shí)候一樣的疑惑:值類型在托管堆中不會(huì)分配內(nèi)存,為什么可以按地址進(jìn)行傳遞呢?值類型雖然活在線程的堆棧中,它本身代表的就是數(shù)據(jù)本身(而區(qū)別于引用數(shù)據(jù)類型本身不代表數(shù)據(jù)而是指向一個(gè)內(nèi)存引用),但是值類型也有它自己的地址,即指針,現(xiàn)在用ref和out修飾后,傳遞的就是這個(gè)指針,所以可以實(shí)現(xiàn)修改后a,b的值真正的交換。這就是ref和out給我們帶來(lái)的好處。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多