游哥今天遇到了一個關於結構體的神現象。
簡單點來說就是:
一個結構體,里面沒有屬性,可以不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進行了賦初始操作,所以后面就不出錯了。
一點淺見 歡迎批評指正