在看後面的內容之前,請先猜猜上面四個Console.WriteLine()的輸出結果都是什麼? 第一個,沒什麼好說的,各種教材上都說爛了。值類型作為參數傳遞的時候編輯的是它的副本。 第二個,有的人會答”321″,其實不是這樣的。我們先往後看。 第三個,和第四個比較容易混淆。第三個是對傳參傳進來的對象 ...
1 namespace 4what.program.code 2 class Student 3 { 4 public string Name { get; set; } 5 } 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 int i = 15; 11 ChangeValue(i); 12 Console.WriteLine(i); 13 14 string str = "123"; 15 ChangeValue(str); 16 Console.WriteLine(str); 17 18 Student stu1 = new Student() { Name = "Name" }; 19 20 UpdateStudentNameByProperty(stu1); 21 Console.WriteLine(stu1.Name); 22 23 Student stu2 = new Student() { Name = "Eman" }; 24 25 UpdateStudentNameByObject(stu2); 26 Console.WriteLine(stu2.Name); 27 28 Console.Read(); 29 } 30 31 static void ChangeValue(int param) 32 { 33 ++param; 34 } 35 static void ChangeValue(string param) 36 { 37 param = "321"; 38 } 39 static void UpdateStudentNameByObject(Student param) 40 { 41 param = new Student() { Name = "Tom" }; 42 } 43 static void UpdateStudentNameByProperty(Student param) 44 { 45 param.Name = "Tim"; 46 } 47 } 48 }
在看後面的內容之前,請先猜猜上面四個Console.WriteLine()的輸出結果都是什麼?
第一個,沒什麼好說的,各種教材上都說爛了。值類型作為參數傳遞的時候編輯的是它的副本。
第二個,有的人會答”321″,其實不是這樣的。我們先往後看。
第三個,和第四個比較容易混淆。第三個是對傳參傳進來的對象賦值,實際上修改了參數的引用。在傳參過程中,param拿到了stu1的地址,我們修改了param指針指向的地址,然而並未對stu1地址的對象做任何修改。所以stu1.Name的值還是”Name”。
回頭看第二個,現在應該不難理解了吧?
第四個,param是指向stu2在記憶體中的地址。通過param.Name拿到的就是stu2.Name屬性的地址。因此對其修改將直接影響到後面stu2.Name的輸出。
現在什麼是值類型?什麼又是引用類型?
嚴格意義上說,值類型和引用類型的區別是記憶體分配方式。值類型在棧上,引用類型在堆上。上述第二個例子非常混淆人的視聽。判斷數據經過方法調用進行傳參並修改後,數據的值是否發生變化的依據是看他在棧上還是堆上。而不是單純的靠值類型還是引用類型來判斷。這一點身邊很多的人包括有些教材都對初學者造成了誤導。
我們再看下麵這道練習題:
namespace net.heavensfeel.code.csharp { class Student { public string Name { get; set; } public int Age { get; set; } } class Program { static void Main(string[] args) { Student stu = new Student() { Name = "Name", Age = 18 }; ChangeStudentAgeByProperty(stu.Age); Console.WriteLine(stu.Age); } static void ChangeStudentAgeByProperty(int param) { ++param; } } }
現在好好想想Console.WriteLine()方法輸出的值是多少?這裡就不貼圖了。想知道答案自己敲一遍運行一下就知道了。一定要想清楚為什麼。
我在上初中的時候,數學老師每講完一道題,都會給我們一段時間讓我們給同桌再互相講一遍。如果某些細節上模棱兩可,就會講到一半就講不下去了。似懂非懂不如不懂。我們以為我們已經掌握的知識,只有在用的時候,在說出來的時候才能看出掌握的是否牢固。編程也是這樣,經常我們會遇到差不多是這樣,那樣又行得通的約定。經過關哥的調教決定以後對這些細節一定要想清楚為什麼然後記下來。雖然很難在實際工作中用到,但探索的過程很過癮不是麽!
在實際的開發過程中,還要避免寫這種混淆視聽的代碼,來提高代碼的可讀性。減少在交流上造成的困擾。