02.C#可空類型、默認參數、LINQ(一章1.3-1.4)
利用上班時間發個隨筆,不知領導會不會看到,可能會有同事看到也說不定啊:)
關于可空類型,在C#1中沒有這個概念,在C#3中引入的。那比如我們要實現一個表示人的類,人有名字和年齡兩個屬性,如何表示一個沒有年齡的人呢?
一般作法會將一人int類型封裝成一個引用類型,有人的類中使用成員屬性,該屬性的類型為剛封裝的引用類型,如下
1 public class Person 2 { 3 private string name; 4 private PersonAge age; 5 6 public Person(string name, PersonAge age) 7 { 8 this.name = name; 9 this.age = age; 10 } 11 12 } 13 14 //C#1中使用一個一個引用包裝器類 15 16 public class PersonAge 17 { 18 public int Age; 19 public bool HasAge; 20 }
那要判斷是否有年齡,如Person有一個實例p,則要判斷p對象中的私有屬性age的HasAge是否為true,true表示有年齡,反之沒有。這樣做顯然會引入大量不需要的類,且這些類中有功能重復的、表示一個標示的bool類型的屬性。在C#3中引入可空類型,實現方式為新增了一個NullAble<T>的結構,相信實現應該和我們的PersonAge一樣,只是現在這個系統默認支持的,何不樂乎~
1 public class Person1 2 { 3 private string name; 4 private int? age; 5 6 public Person1(string name, int? age) 7 { 8 this.name = name; 9 this.age = age; 10 } 11 }
結合C#4中提供的可選參數和默認參數,則可以使用null來初始化age這個值,當需要判斷人是否有年齡,只需判斷p的私有屬性age是否為null即可。
1 public class Person2 2 { 3 private string? name; 4 private int? age; 5 6 public string? Name { get { return name; } set { name = value; } } 7 public int? Age { get { return age; } set { age = value; } } 8 9 10 public Person2(string? name, int? age = null) 11 { 12 this.name = name; 13 this.age = age; 14 } 15 }
在入口類中去判斷
1 Person2 p2 = new Person2(null, null); 2 3 //可以使用"?"用null來賦值,來判斷是否有名字和年齡 4 5 if (p2.Age == null) 6 { 7 Console.WriteLine("這個人沒有年齡!!!"); 8 } 9 10 if (p2.Name == null) 11 { 12 Console.WriteLine("這個人沒有名字!!!"); 13 }
總結下,其實只要記住在非引用類型后加一個"?",則可以使用null來賦值。如int? a=null、short? b=null ...
下面來說下LINQ(語言集成查詢),重新寫一個Book類,如下
1 public class Book 2 { 3 public string Author { get; set; } 4 public int PageSize { get; set; } 5 6 public Book(string author, int pageSize) 7 { 8 Author = author; 9 PageSize = pageSize; 10 } 11 12 public static List<Book> GetBooks() 13 { 14 return new List<Book> { 15 new Book("fish0",800), 16 new Book("fish1",1800), 17 new Book("fish2",2800), 18 new Book("fish3",3800), 19 new Book("fish4",4800), 20 new Book("fish5",5800) 21 }; 22 } 23 }
入口頁面使用如下
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 6 List<Book> list = Book.GetBooks(); 7 //選擇書的頁數大于1000的書并打印 8 9 var matching = from Book b in list 10 where b.PageSize > 100 11 select b; 12 foreach (var m in matching) 13 { 14 Console.WriteLine(m.Author + " " + m.PageSize); 15 } 16 17 Console.ReadKey(); 18 } 19 }
常常和LINQ一起使用的關鍵字,我覺得是var,因為想讓編譯器判斷是什么類型,這個就是隱式類型,省去一些繁雜的類型輸入。LINQ的語法和SQL幾乎相同,學習的成本會很小,SQL中的join、order by、group by等都可以在C# LINQ中找到對應的法。
在使用EF等其它ORM框架時,使用LINQ能大大減少代碼量,而且很多的查詢操作都是延時查詢,并不是一次性取出所有的數據,再從中進行篩選,而是通過LINQ生成SQL語句,然后到數據庫中查詢。
請斧正。