嘗嘗C#的語法糖(自動屬性/匿名方法/Lamda表達式等)-小心蛀牙!


-語法糖意指那些沒有給計算機語言添加新功能,而只是對人類來說更“sweet”的語法,意在使得編程風格更易讀。C#2.0,3.0發布的新特性,除了泛型不是語法糖,其他所有的新特性幾乎都是語法糖。

-但初學者往往因為不了解這些語法糖,從而在閱讀代碼的時候,難以理解其真正的運作方式。最著名的莫過於Lamda表達式,第一次看到它,很多人都會頂個大問號把。。。

-文章前面會伴隨一些讓人看着想吐槽的代碼,請大家自行河蟹。然后我們會介紹一些語法糖來潤色一下,方便初學者們知道這些語法糖的原始意義。

  我們來做一個List<T>類的練習。我會寫一個很蛋疼的例子(盡量不用語法糖,當然這很難避免)。首先我定義了一個學生類

public class Student
{
    private string num;
    public string Num { get { return num; } }
    private string name;
    public string Name { get { return Name; } }
    public Student(string num, string name)
    {
        this.num = num;
        this.name = name;
    }
    public override string ToString()
    {
        return num + ":" + name;
    }
}

  現在練習下List<T>的FindAll()方法,它的聲明如下

public T FindAll(Predicate<T>match)

  FindAll方法把Predicate<T>作為參數,Predicate<T>是一個委托,它引用一個謂詞方法-返回布爾值的方法。如果謂詞返回true,表示有一個匹配。

  所以我寫了一個FindStudent類來定義謂詞。這個方法用要搜索的學生的學號來初始化,FindPredicate()接收一個student對象,比較student對象的學號與構造函數中設置的學號,返回true or false。

 public class FindStudent  //修正於2010/4/20 感謝 Terry_Huang和 Jack Afa指正
    {
        private string num name;
        public FindStudent(string num Name)
        {
            this.num = num;
this.name = Name; } public bool FindPredicate(Student student) { return student.Name == name; } }

  最后在一個控制台程序里搜索名字叫John的學生。

  class Program
    {
        static void Main(string[] args)
        {
            List<Student> Students = new List<Student>();
            Students.Add(new Student("001", "John"));
            Students.Add(new Student("002", "Marry"));
            Students.Add(new Student("003", "John"));
            FindStudent finder = new FindStudent("John");
            foreach (var student in Students.FindAll(new Predicate<Student>(finder.FindPredicate)))
            {
                Console.Write(student);
            }
        }
    }

  有沒有人看到這已經扛不住了呢,特別是對FindStudent類和FindAll的冗長的用法?

  下面我們來一點一點的潤色把。

  甜死你1號-自動屬性:只需在定義一個類時指定屬性名,C#3.0編譯器將自動實現相應的內部的private變量,並自動生成set訪問器和get訪問器。

  甜死你2號-對象初始值設定項:在自動屬性的前提下,在創建對象時可以對任何可訪問的屬性或字段賦值,而不需要顯示的調用構造函數。

  基於這兩個特性,我們來修改一下Student類:

public class Student
{
    public string Num { get; set; }

    public string Name { get;set; }

    public override string ToString()
    {
        return Num + ":" + Name;
    }
}

 

  自動屬性會自動生成私有變量,不需要顯示的聲明,並且可以直接通過對象初始值設定項對可訪問的屬性和字段賦值,構造函數也不是必須的。呃,是不是清爽多了。

  甜死你3號-匿名方法 : 我們之前必須首先聲明方法后才能在委托中使用,C#2.0引入匿名方法,可以delegate{ //dosomething}的形式以一種“內聯”的方式來編寫方法代碼,將代碼直接與委托實例相關聯,從而使得委托實例化的工作更加直觀和方便。

  有些時候我們需要臨時保存一些運算的中間結果,我們常常會去聲明一個新的類型,以方便保存這些中間結果。表面上 看起來這很正常,而細想之后就會發現,這個新類型只服務於這個函數,其它地方都不會再使用它了,就為這一個函數而去定義一個新的類型,確實有些麻煩,比如FindStudent類。

  有了匿名方法FindStudent類已經沒有存在的意義了(大快人心?),因為自動屬性的關系,我們可以直接訪問屬性,並且用匿名方法來代替謂詞。

  插播廣告:

  甜死你4號-集合初始值設定項:我們除了可以像初始化數組一樣,初始化對象之外,同樣對於集合也可以不用再重復的Add來增加集合項了,我們來看新的Main函數:

    static void Main(string[] args)
        {
            List<Student> Students = new List<Student>()
            {
             new Student(){ Num="001", Name="John"},//使用對象初始值設定項初始化對象,代替構造函數
             new Student(){ Num="002", Name="Marry"},
             new Student(){ Num="003", Name="John"}
            };//使用集合初始值設定項初始化集合,不用重復調用Add方法
            foreach (var student in Students.FindAll(delegate(Student student) { return student.Name == "John"; }))//使用匿名方法完成FindStudent類的功能
            {
                Console.WriteLine(student);
            }
            Console.ReadKey();
        }

  是不是看着順眼多了。不過foreach這句還是有點不順眼。腫么辦,我們只好開大招了。

  甜死你終結者號-Lamda表達式:它是升級版的匿名方法,其作用是簡化匿名方法的寫法。寫法(形參列表)=>{函數體}

  delegate(Student student) { return student.Name == "John"; }這個匿名方法為例,我們的參數就只有student一個,形參我們就使用s代替。

  Lamda表達式就是 s=>s.Name=="John"。

  順便我們用一下List<T>的ForEach方法。

  又一條廣告: 

  甜死你路人號-匿名類型: 使用var關鍵字來進行類型聲明,而不需要顯示的聲明類型,具體的類型將由編譯器來推斷。

  最終的Main函數就是:

   static void Main(string[] args)
        {
            List<Student> Students = new List<Student>()
            {
             new Student(){ Num="001", Name="John"},//使用對象初始值設定項初始化對象,代替構造函數
             new Student(){ Num="002", Name="Marry"},
             new Student(){ Num="003", Name="John"}
            };//使用集合初始值設定項初始化集合,不用重復調用Add方法
            var John = Students.FindAll(s => s.Name == "John");//使用var聲明匿名類型,其實John是個List<Student>
            John.ForEach(j => Console.WriteLine(j));//使用Lamda表達式
            Console.ReadKey();
        }

  這樣的代碼看着就很舒服了。

  當然語法糖還有很多,如文章開頭所說,C#的新特性大多是語法糖。當然還有一些其他的語法糖,比如三元運算符Test?expression1:expression2就有一個語法糖,寫作

  expression1??expression2   2選1,expression1為null則執行expression2。反之執行expression1。

  歡迎大家補充,這里就不多做介紹了。

  --------------------------------------------我是分割線------------------------------------------------

  語法糖能夠增加程序的可讀性,但凡事都有兩面性。比如你需要在屬性的get方法中寫一些邏輯,顯然自動屬性就不適用了。所以不必強求。

  咱別硬吃把牙吃壞了。。。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM