C#入參使用引用類型要加ref的原因解析
摘一段來自官網的說明 :方法的參數(shù)列表中使用 ref 關鍵字時,它指示參數(shù)按引用傳遞,而非按值傳遞。 ref 關鍵字讓形參成為實參的別名,這必須是變量。 換而言之,對形參執(zhí)行的任何操作都是對實參執(zhí)行的。
大體意思就是將實慘的引用作為參數(shù)傳遞,如果入參不加ref修飾,本身傳遞的是實參的值到方法中。
那什么是值,什么是引用?大體可以理解為堆棧的區(qū)別,在.net中大多數(shù)實例存在于托管堆棧中。struct,int32,int64,double,enum等數(shù)據類型聲明的實例存在棧中,而string,class,delegate等存在于堆中。前者一般稱為值類型,后者則叫做引用類型,那么引用類型和值類型在內存中的大概圖如下:
可以看到引用類型被存儲的時候真正內容存在堆中,而在stack中存儲了一個堆中地址的引用指向堆中真正內容。
ref修飾入參的常用場景
當我們希望一個已有返回值的方法能夠修改我一個外部基本類型的值的時候,我們可以將該參數(shù)加上ref關鍵字作為入參。具體原理其實就是將棧中具體的值替換為了棧的引用,說白了就是地址,幻想一下本來你高考作弊只是后臺改了一下自己成績和學霸一樣,學霸的人生沒有受到影響,現(xiàn)在你干脆把學霸的試卷改成了自己名字,學霸直接被你影響只能進廠打螺絲了,當然這個比喻不是很貼切,大家理解到意思就行。
那么為什么引用類型的入參我們不需要要添加ref?因為從上圖我們能看出來棧中存儲的本來就是引用類型的地址,所以引用類型不需要添加ref關鍵字,當你在方法內部修改了入參的一些屬性值,外面的實慘依舊會受到影響。
引用類型添加ref的作用是啥?
我們在實際開發(fā)中還是能夠碰到一些引用類型添加ref的場景。其實道理也是一樣的,就是將引用類型的棧的地址傳遞到了方法中,那么和不添加有啥區(qū)別?我們來看看下面的代碼:
Student student1 = new Student("Jack"); Student student2 = new Student("Lucy"); WithoutRef(student1); WithRef(ref student2); Console.WriteLine($"不帶ref的方法---{student1.Name}"); Console.WriteLine($"帶ref的方法---{student2.Name}"); Console.Read(); //不帶ref的方法 static void WithoutRef(Student stu) { stu.Name = "Bruce"; } //不帶ref的方法 static void WithRef(ref Student stu) { stu.Name = "Bruce"; } public class Student { public Student(string name) { Name = name; } public string Name { get; set; } }
可以看到結果一樣的,兩個實例的名字都變了
那我們再看看下面的代碼:
Student student1 = new Student("Jack"); Student student2 = new Student("Lucy"); WithoutRef(student1); WithRef(ref student2); Console.WriteLine($"不帶ref的方法---{student1.Name}"); Console.WriteLine($"帶ref的方法---{student2.Name}"); Console.Read(); //不帶ref的方法 static void WithoutRef(Student stu) { stu = new Student("Bruce"); } //不帶ref的方法 static void WithRef(ref Student stu) { stu = new Student("Bruce"); } public class Student { public Student(string name) { Name = name; } public string Name { get; set; } }
我們發(fā)現(xiàn)第一個不帶ref的方法名字沒有發(fā)生變化。
代碼的變化就是第二個例子重新new了一下,我們根據上面的原理分析就能知道為啥。由于ref將引用類型的棧地址傳遞過去了,new關鍵字大體就是在堆中開辟一個新空間,然后將空間地址存儲到棧中,由于ref將棧地址傳遞過來了,所以就將棧中的存儲地址替換為了新開辟的堆地址了,而不帶ref的引用類型本身傳遞的只是堆中地址的引用,所以new關鍵字等于說將形參重新開辟空間和分配了,和實參已經不是同一個地方了。
總結
ref傳遞的是棧地址
不帶ref傳遞的是棧中存儲的值,可能是一個值,也可能是一個地址引用。
到此這篇關于C#入參使用引用類型要加ref的原因解析的文章就介紹到這了,更多相關c#引用類型加ref內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#實現(xiàn)把dgv里的數(shù)據完整的復制到一張內存表的方法
這篇文章主要介紹了C#實現(xiàn)把dgv里的數(shù)據完整的復制到一張內存表的方法,需要的朋友可以參考下2014-08-08