C#開發的進化史(排序和過濾)

    本次不會改變product類型,會使用產品列表,並按名稱排序,而後找出最貴的產品spa

1、按名稱對產品進行排序.net

    以特定順序顯示一個列表的最簡單方式就是先將列表排好序,在遍歷顯示其中的項。blog

 (一) 在.net1.1中,這要求使用ArrayList.Sort,要求提供一個IComparer實現。也可讓product類型實現IComparable,但那就只能定義一種排序順序。很容易就會想到,之後除了須要按名稱排序,還可能須要按價格排序排序

                          使用IComparer對ArrayList進行排序接口

 class productNameComparer : IComparer
    {
        public int Compare(object x, object y)
        {
            Product first = (Product)x;
            Product second = (Product)y;
            return first.Name.CompareTo(second.Name);
        }

    }

......
         ArrayList products = Product.GetSanpleProducts();
            products.Sort(new productNameComparer());
            foreach (Product product in products)
            {
                Console.WriteLine(product);
            }
            Console.ReadKey();        

  要注意的第一件事是:必須引入一個的類型來幫助排序。雖然這並非一個很大的問題,但假如在一個地方只是項按名稱進行排序,就會感受編譯工做過於繁重。其次,注意Comparer方法中強制類型轉換。強制類型轉換至關於告訴編譯器:「我知道發比你多一點點,」可是,也就意味着多是錯誤的。若是GetSanpleProducts返回的是ArrayList包含一個字符串,那麼代碼會出錯——由於在比較時試圖將字符串強制轉型爲product。開發

  (二)在給出排序列表的代碼中也進行了強制類型轉換。這個轉換不如剛纔的轉換顯示,由於是編譯器自動進行的。foreach循環會隱式將列表中的每一個元素轉換爲product類型。這樣的狀況在執行時會失敗,在C#2「泛型」能夠幫助解決這些問題字符串

                                              使用Icomparer對List<product>進行排序編譯器

  class productNameComparer : IComparer<Product>     {
        public int Compare(Product x, Product y)
        {
            return x.Name.CompareTo(y.Name);
        }
    }
......
 List<Product> products = Product.GetSanpleProducts();
            products.Sort(new productNameComparer());
            foreach (Product product in products)
            {
                Console.WriteLine(product);
            }

            Console.ReadKey();

  對產品進行比較的代碼變得更簡單,由於一開始提供的就是product。不須要進行強制類型轉換。相似地,foreach循環中隱式的類型轉換也被取消了。編譯器仍然會考慮將序列中的源類型轉換爲變量的目標類型,但它知道這時兩種類型均爲product,所以不必產生任何用於轉換的代碼。產品

  但願能直接指定要進行的比較,就能開始對產品進行排序,而不須要實現一個接口來作這件事。it

                                              使用Comparison對List<product>進行排序

List<Product> products = Product.GetSanpleProducts();
            products.Sort(delegate (Product x, Product y)
            {
                return x.Name.CompareTo(y.Name);
            });

            foreach (Product product in products)
            {
                Console.WriteLine(product);
            }
            Console.ReadKey();

  如今已經不在須要productNameComparer類型了。以粗體印刷的語句實際會建立一個委託實例,將這個委託實例提供給Sort方法來執行比較

(三)已經修正了在C#1的版本中不喜歡的全部東西。可是,這並非說C#3不能作到更好。首先,將匿名方法替換成一種更簡潔的建立委託實例的方式

                                              lambda表達式中使用Comparison排序

 List<Product> products = Product.GetSanpleProducts();
            products.Sort((x, y) => x.Name.CompareTo(y.Name));
            foreach (Product product in products)
            {
                Console.WriteLine(product);
            }

            Console.ReadKey();

  看到了一種奇怪的語法(一個lambda表達式),它仍然建立了一個Comparison<product>委託,只是代碼量減小。這裏沒必要使用delegate關鍵字來引入委託,甚至不須要指定參數類型

  除此以外,使用C#3還有其餘好處,如今,能夠輕鬆的按順序打印名稱,同時沒必要修改原始產品列表。

                                              使用擴展方法對List<product>進行排序

 List<Product> products = Product.GetSanpleProducts();
            foreach (Product product in products.OrderBy(p=>p.Name))
            {
                Console.WriteLine(product);
            }

            Console.ReadKey();

  這裏彷佛調用一個OrderBy方法,但查閱一下MSDN,就會發現這個方法在LIst<product>中根本不存在。之因此能調用它,是因爲存在一個擴展方法。這裏實際不在是「原地」對列表進行排序,而只是按特定的順序獲取列表的內容。有時,須要更改實際的列表;但有時,沒有任何反作用的排序顯得更「善解人意」。

(四)總結

  重點在於,如今的寫法更簡潔,可讀性更好。想法是「列表按名稱排序」,如今的代碼正是這樣作的。並非「列表經過將產品的名稱與另外一個產品的名稱進行比較來排序」,就像C#2代碼所作的那樣。也不是使用知道如何將一個產品與另外一個產品進行比較的另外一個類型的實例來排序。這種簡化的表達方式是C#3的核心有事之一。既然單獨的數據查詢和操做是如此簡單,那麼在執行更大規模的數據處理時,仍然能夠保存代碼的簡潔性和可讀性,這進而鼓勵開發者以一種「以數據爲中心」的方式來觀察世界。

                                在C#2和C#3中用於簡化排序的特性

  1.C#1:弱類型的比較功能不支持委託排序

  2.C#2強類型的比較更能,委託比較,匿名方法

  3.C#3:表達式,擴展方法,容許列表保持爲排序狀態

相關文章
相關標籤/搜索