代碼下載:點我下載
首先祝大家2015新年快樂!
新的一年,新的開始。來博客園安家已經快兩個月了。每天看博客、寫博客、評論、回答博問已經漸漸養成了一種習慣。可以很明顯的感覺到泡在博客園裡真的可以學到很多,不論是技術文章的還是一些記敘經歷、抒發感想的隨筆,都讓我從各個方面受益良多。不知道大家是否和我一樣,就是感覺博客園有一種特殊的魔力,讓你沒事就想上去看一眼,看上面是不是又有人發了新文章,而且累了的時候在上面看看非技術的東西也能放松自己。
有時會問自己:在博客園上花了這些時間和精力,是否值得?畢竟這也算是"義務勞動",不為自己創造任何價值,通俗點說就是不掙錢。但是每想一次這個問題我都會更加堅定自己的選擇。堅持博客園的理由有三:
因此,堅持博客園絕對是一個現實的決定。我相信我能一直做下去。
回到我們的博客本身。之前寫了10篇MVC5 + EF6 + Bootstrap3系列教程,今年會繼續寫下去。畢竟這三項技術都是我大大看好的。在寫這個系列的時候,有些遺憾的是,很多C#本身的技術點與MVC關系不大。詳細寫的話怕跑題,不寫怕讀者看不懂,一直都有點尴尬。因此我新開了這個專題[C#詳解]來把那些曾經要講而沒有講的東西一一講講清楚。這樣自己也安心了。因此看了[C#詳解]系列會使你在看MVC5 + EF6 + Bootstrap3系列時更加清楚明白。而看[C#詳解]時也可以去MVC5 + EF6 + Bootstrap3找到這些知識點的實際應用場景。這樣相輔相成,效果應該很好。
在解釋自動屬性之前有必要先說說屬性。
我們知道要符合面向對象編程的原則,一個類裡面的變量最好是私有的。如下所示:
class Student { private int _id; }
這樣保證了類的封裝性。可是把它封裝起來總得有辦法從外部訪問它,要不然就沒有存在的必要了。因此這裡我們就用到了屬性。代碼如下所示:
1 class Student 2 { 3 private int _id; 4 public int Id 5 { 6 get 7 { 8 return _id; 9 } 10 set 11 { 12 _id = value; 13 } 14 } 15 }
上面代碼中第4行定義了一個名為Id的屬性,通過它就能訪問到私有變量_id。Id屬性內部有get和set兩個訪問器,get訪問器用於獲取私有變量的值,set訪問器用於給私有變量賦值。下面的代碼展示如何使用屬性:
1 Student student = new Student(); 2 student.Id = 3; 3 Console.Write(student.Id);
第2行調用set訪問器給Id賦值,第3行,調用get訪問器獲取Id值顯示出來,結果如下:
屬性的功能不僅如此,我們可以給get訪問器加入代碼來對輸出做處理或者給set加入代碼來對賦值做處理。示例如下:
1 class Student 2 { 3 private int _id; 4 public int Id 5 { 6 get 7 { 8 return _id + 100; 9 } 10 set 11 { 12 if (value > 0) 13 { 14 _id = value; 15 } 16 else 17 { 18 _id = 0; 19 } 20 } 21 } 22 }
第8行的代碼使Id屬性在輸出時加100,第12-19行,使Id屬性在賦值時若值小於0,則賦值為0。
用下面代碼調用上面的類。
1 Student student = new Student(); 2 student.Id = -3; 3 Console.Write(student.Id);
第二行執行後Id屬性會賦值為0,然後在輸出時會變為100。
屬性的定義是繁瑣的,這裡我們就可以用自動屬性來簡化代碼。同樣是定義一個對輸入輸出不做任何特殊處理的屬性,我們可以這樣寫:
1 class Student 2 { 3 public int Id { get; set; } 4 }
第3行就是我們的自動屬性了,其寫法就是在屬性後加{ get; set; }。省了私有變量和訪問器的定義,一行就搞定,但其功能還是和以前的屬性一模一樣。這就是自動屬性的好處。但是自動屬性不能實現前面提到過的對輸入輸出做特殊處理。
另外,想要把一個屬性變為只讀的,用自動屬性可以這樣寫:
1 class Student 2 { 3 public Student(int id) 4 { 5 Id = id; 6 } 7 public int Id { get; private set; } 8 }
上面代碼中第7行在set訪問器前面加上private,屬性賦值沒辦法被外部調用,自然是變成只讀屬性了。但在第3-6行要記得加入構造函數給屬性賦初值。這個類的調用方法如下:
1 Student student = new Student(3); 2 Console.Write(student.Id);
第1行用構造函數給Id賦值,第2行獲取所賦的值。結果如下:
點我看自動屬性
初始化器分為對象初始化器和集合初始化器。下面一一介紹。
對象初始化器的作用,簡單點說就是可以使我們初始化一個類的代碼變得更簡潔。比如下面這個類:
class Person { public string Name { get; set; } public int Age { get; set; } public string Address { get; set; } }
我們要初始化它並對它賦值的話通常要這樣:
Person person = new Person(); person.Name = "Slark"; person.Age = 100; person.Address = "Xi'an";
這裡我們用了一行創建對象語句,加三行賦值語句。這裡光person這個變量就出現了4遍,繁瑣。用對象初始化器來代替這些操作:
Person person = new Person { Name = "Slark", Age = 100, Address = "Xi'an" };
同樣的效果,對象初始化器只用了一行,簡潔!可以看到對象初始化器將創建對象和賦值合為一行,其中賦值就是在後面大括號裡做的。這裡的賦值可以給所有屬性賦值,也可以給部分屬性賦值。
既然要講集合初始化器,那麼我們就先來創建一個集合:
List<int> intList = new List<int>(); intList.Add(1); intList.Add(2); intList.Add(3);
好,這裡我們用4行代碼創建了一個3個元素的集合。集合初始化器的出現大大減少了我們對這種操作的代碼量。其對應的集合初始化器代碼為:
List<int> intList = new List<int> { 1, 2, 3 };
嗯,真的少寫了很多。集合初始化器的原理也很簡單,就是它默默的為我們調用了List的Add方法依次為我們添加了這3個元素。
這裡我們再給一個綜合運用集合初始化器和對象初始化器的例子:
List<Person> personList = new List<Person> { new Person { Name = "Slark1", Age = 101, Address = "Xi'an1" }, new Person { Name = "Slark2", Age = 102, Address = "Xi'an2" }, new Person { Name = "Slark3", Age = 103, Address = "Xi'an3" } };
代碼裡用集合初始化器初始化了personList,然後用對象初始化器初始化了3個Person對象實例。這其中省了多少代碼,真是不談了。
點我看初始化器應用實例
擴展方法,簡單點說就是可以在不改變現有類的情況下給這個類添加方法。我覺得擴展方法的最大意義在於我們可以給那些我們根本無法修改的類,比如String,添加我們自定義的方法。既然無法通過修改來添加,那就只能通過擴展了。
這讓我想到了開閉原則(Open-Close Principle,OCP):一個軟件實體應該對擴展開放,對修改關閉。
既然類對擴展開放了,我們就趕緊來試試吧!
先試著給String添加一個DoubleString方法,就是把這個字符串輸出兩遍。
先創建一個靜態類StringExtension:
1 static class StringExtension 2 { 3 public static string DoubleString(this string str) 4 { 5 return str + str; 6 }
7 }
注意第1行,我們把要擴展的方法放在一個類裡,並且這個類必須是靜態類,要加static。類的名字隨便起,無所謂。第3-6行就是我們想要擴展的方法。這個方法比較特殊,在定義的時候要寫成靜態方法,但是在調用的時候要當實例方法用。這個方法的參數寫成this string str 表示要把這個方法加到String類中。但是這個方法在調用時是不能加參數的。
調用方法如下:
string str = "ABCD"; Console.Write(str.DoubleString());
可以看到,擴展的方法DoubleString被調用的時候被當作實例方法,並且沒有參數。運行結果如下:
結果符合我們的預期。
如果要給擴展方法帶參數怎麼辦?示例代碼如下:
1 static class StringExtension 2 { 3 public static string RepeatString(this string str, int row,int column) 4 { 5 string s = string.Empty; 6 for (int i = 0; i < row; i++) { 7 for (int j = 0; j < column; j++) 8 { 9 s += str + " "; 10 } 11 s += "\r\n"; 12 } 13 return s; 14 } 15 }
注意第3行這裡一共有3個參數,其中後兩個參數會在調用這個擴展函數的時候被賦值,這裡這個RepeatString函數會把一個字符串寫成幾行幾列的矩陣。
調用方法如下:
string str = "ABCD"; Console.Write(str.RepeatString(3,4));
調用時的第一個參數對應定義時的第二個參數,調用時的第二個參數對應定義時的第三個參數。顯示結果如下。
點我看擴展方法實例
呼呼~ 終於寫完了,腰酸背痛腿抽筋。
喜歡就推薦下吧!
作者:Slark.NET
出處:http://www.cnblogs.com/slark/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。如有問題或建議,請多多賜教,非常感謝。