遊哥今天遇到了一個關於結構體的神現象。
簡單點來說就是:
一個結構體,裡面沒有屬性,可以不new就使用。但在結構體裡面寫了個屬性就必須要new才能使用,這是為什麼呢?
直接上代碼:
struct Dog //狗的結構體{ public int age;}struct Cat //貓的結構體{ public int Age { get; set; }}class Program{ public static void Main() { //情況A Dog dog1; dog1.age = 3; //片段1 Console.WriteLine(dog1.age); //不出錯 Cat cat1; cat1.Age = 3; //編譯錯誤 Console.WriteLine(cat1.Age); //片段2 //情況B Dog dog2 = new Dog(); dog2.age = 3; //片段3 Console.WriteLine(dog2.age); //不出錯 Cat cat2 = new Cat(); cat2.Age = 3; //片段4 Console.WriteLine(cat2.Age); //不出錯 }}
片斷4不報錯,而片斷2則報錯。
這裡面涉及很多技術細節,你能知道這是為什麼嗎?
遊哥來解答:
1.結構體裡只有欄位,沒有屬性。狗類分析:
片斷1,不出錯。眾所周知,結構體可以不new就使用。
片斷3,不出錯。不new不出錯,new了就更不出錯了。
2.結構體可以new,也可以不new。new與不new的區別是,new為會每一個成員欄位賦一個預設初值(還記得default關鍵字嗎),而不new則不會這麼做。
3.任何一個屬性,編譯器都會自動產生一個與之對應的欄位來儲存資料,比如這裡的Age屬性,就會產生出一個_age來為其儲存資料。(它可能不叫_age,這不是重點,總之你看不到這個欄位,但它確實存在。)
4.瞭解一下,什麼叫資料結構和演算法吧。其實有點扯遠了,簡單來說,可以這麼理解,欄位就是資料結構,而方法和屬性訪問器就是演算法了。(欄位儲存資料,而方法和屬性訪問器對這些資料進行加工計算)。
5.為什麼要提出資料結構和演算法,我要說的重點是:要調用結構體的演算法(各部門請注意,我要來計算了),必須先讓所有的資料就就緒(那些欄位都賦了初值了嗎)。意思就是說,你要調用結構體的任何一個方法或屬性訪問器之前,必須要給所有的欄位賦初始。編譯器不會去關心你的演算法涉及了哪些欄位(編譯器不檢查你的方法體)。甚至是你的演算法沒有涉及任何欄位的訪問,編譯器依然要求你將所有的欄位都賦上初值才能使用。
6.結構裡有屬性。貓類分析:
片斷2,編譯錯誤。那個隱藏的_age沒有賦初值,而你寫cat1.Age=3,是調用了Age的set訪問器,set訪問器是一個演算法,你要使用這個演算法,必須先將所有欄位賦初始,而你的_age沒有賦初值,所以就編譯錯誤了。
片斷4,不會出錯。你在new Cat()時,對_age進行了賦初始操作,所以後面就不出錯了。
一點淺見 歡迎批評指正