寫在最前面
這幾天一直在公司接受培訓,都是一些基礎的知識,同時也乘着這個機會鞏固一下自己的基礎,基礎太重要了。前些時一直看的是多線程方面的知識,接下來我會寫一些其他方面的知識,畢竟作為一個實習新人得和自己從事的具體方向靠近,不過感覺前些時的多線程學的還不夠,今后有空還會繼續,暫時到此吧、、、
昨天培訓的時候有一個問題是關於ref和out的區別,悲催的我不知道,只曉得它們可以做引用傳遞,具體區別都沒一個概念額,貌似當年教我們C#初級的尹老師提到過一個數字交換實現可以用這個,不過當時也就僅此僅此,今天來學習下下
首先聲明下哈,此文參考了網上部分文章內容,然后結合自己的了解和總結,有不對的盡管拍磚
關於ref
經常聽到值類型和引用類型,其實本質就是一個存儲值一個存儲地址,看看下面一段代碼:
1 public class Test 2 { 3 public int num; 4 public Test(int x) 5 { 6 this.num = x; 7 } 8 public void ChangeNum(Test x) 9 { 10 x = new Test(100); 11 } 12 } 13 class Program 14 { 15 static void Main(string[] args) 16 { 17 Test ts = new Test(10); 18 ts.ChangeNum(ts); 19 Console.WriteLine(ts.num); 20 Console.ReadKey(); 21 } 22 }
對於以上代碼,你認為會輸出什么結果?10?100?正確結果是10,猜100的肯定有疑問了、、、
接下來我改兩個位置,就不復制整個了,貼出改位置的兩個位置,如下所示:
ts.ChangeNum(ref ts); //改上面第18行 public void ChangeNum(ref Test x) //改上面第8行
對於這次的結果又得探討了,10?還是100?正確結果為100
以上截圖,左邊是原始代碼變量ts和x的地址,右邊是修改兩個位置后的ts和x的地址,從上面我們可以清晰的看見左圖ts地址(0x05f0eb2c)和x地址(0x05f0eacc)不同,右圖中ts的地址(0x0568ee6c)和x的地址(0x0568ee6c)相同。就是由於原始代碼中Main函數中的ts和Test中的x不是同一個變量,所以后面執行18行代碼不會對num值產生任何影響,而后面的兩行代碼就不同,因為所指向的是同一個變量,所以結果自然得以修改變為100
關於out
還是來看一段代碼,事實比較好說話,呵呵:
1 public class Test 2 { 3 public int num; 4 public Test(int x) 5 { 6 this.num = x; 7 } 8 public void ChangeNum(out Test x) 9 { 10 x = new Test(100); 11 } 12 } 13 class Program 14 { 15 static void Main(string[] args) 16 { 17 Test ts = new Test(10); 18 Test x; 19 ts.ChangeNum(out x); 20 Console.WriteLine(ts.num); 21 Console.WriteLine(x.num); 22 Console.ReadKey(); 23 } 24 }
以上這段代碼執行打印的兩個結果也是不同的,分別打印10和100,原理和上面差不多一樣,是不是感覺和上面講的ref很有點象,沒錯,所以有了今天的標題“關於ref與out的區別”,接下來談談其區別吧!
關於out和ref的區別
作為都可以作為引用傳遞,區別在於值傳遞。ref傳遞前必須初始化,而out不必初始化,就算初始化,也會被無視之,out 作為輸出參數,可以解決函數只有一個返回值的問題
1 static void Main(string[] args) 2 { 3 Program pg = new Program(); 4 int x; 5 pg.Method_1(out x); 6 Console.WriteLine(x); 7 int y = 1; 8 pg.Method_2(ref y); 9 Console.WriteLine(y); 10 Console.ReadKey(); 11 } 12 13 public void Method_1(out int x) 14 { 15 x = 2; //這一句必須要,不然報錯 16 Console.WriteLine("調用Medthod_1"); 17 } 18 19 public void Method_2(ref int x) 20 { 21 x++; 22 Console.WriteLine("調用Medthod_2"); 23 }
運行結果:
懷舊一下當年尹老師講的a=5和b=10,a與b數值交換,就是用的ref
1 public void yy(ref int x,ref int y) 2 { 3 int temp; 4 temp = x; 5 x = y; 6 y = temp; 7 } 8 static void Main(string[] args) 9 { 10 Program pg = new Program(); 11 int a = 5; 12 int b = 10; 13 Console.WriteLine("a:" + a + ",b:" + b); 14 pg.yy(ref a,ref b); 15 Console.WriteLine("a:"+a+",b:"+b); 16 Console.ReadKey(); 17 }
然后以上代碼改為用out實現:
1 public void yy(int a,int b,out int x,out int y) 2 { 3 x = b; 4 y = a; 5 } 6 static void Main(string[] args) 7 { 8 Program pg = new Program(); 9 int a = 5; 10 int b = 10; 11 Console.WriteLine("a:" + a + ",b:" + b); 12 pg.yy(a,b,out a,out b); 13 Console.WriteLine("a:"+a+",b:"+b); 14 Console.ReadKey(); 15 }
自我感覺吧,在很多地方ref和out可以互換,起到相同的作用,區別僅僅在於ref傳進去的參數必須在調用前初始化,out不必初始化;ref傳進去的參數在函數內部可以直接使用,而out不可以;ref傳進去的參數在函數內部可以不被修改,但out必須在離開函數體前進行賦值。個人感覺ref可以更隨意的使用,out總有那么點別扭,畢竟必須在內部給其賦值。
實習的第一個雙休日
貌似此文扯了些不該扯得,但總的來說都是跟隨筆主要內容有些相關啦,接下來由於培訓內容的相關,得轉移重心了,Linq和EF還得再回去看看,所以后期可能寫點哪方面相關知識。晚睡的習慣還木有改過來,這是個問題得治啊,聽了一晚上的歌,單曲循環"想把我唱給你聽",好晚了,睡覺去也!!!
------如果你覺得此文對你有所幫助,別忘了點擊下右下角的推薦咯,謝謝!------