首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Effective C# 原則 24:優先選擇宣告式程式設計而非命令式程式設計(二)

     編輯:關於C語言

通用比較器實作

同樣,你必須寫程式碼對集合排序,集合元素為添加 DefaultSort 特性的物件。用反射發現正確屬性,比較兩不同物件屬性值。好消息:只寫一次這樣的程式碼。

實作 IComparer 介面

下一步,寫實作 IComparer 的類別(原則 26 詳細討論比較)。IComparer 有 Compare() 比較兩個給定型別物件。將特性放在實作 IComparable 的類別上,定義排序順序。建構函式針對通用比較發現預設排序屬性標記,基於已比較型別。Compare 方法對任何型別兩物件排序,使用預設排序屬性:

internal class GenericComparer : IComparer
{
    private readonly PropertyDescriptor _sortProp;
    private readonly bool _reverse = false;
    public GenericComparer(Type t) : this(t, false) { }
    public GenericComparer(Type t, bool reverse)
    {
        _reverse = reverse;
        object[] a = t.GetCustomAttributes(typeof(DefaultSortAttribute), false);
        if (a.Length > 0)
        {
            DefaultSortAttribute sortName = a[0] as DefaultSortAttribute;
            string name = sortName.Name;
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(t);
            if (props.Count > 0)
            {
                foreach(PropertyDescriptor p in props)
                    if (p.Name == name) { _sortProp = p; break; }
            }
        }
    }
    int IComparer.Compare(object left, object right)
    {
        if ((left == null) && (right == null)) return 0;
        if (left == null) return -1;
        if (right == null) return 1;
        if (_sortProp == null) return 0;
        IComparable lField = _sortProp.GetValue(left) as IComparable;
        IComparable rField = _sortProp.GetValue(right) as IComparable;
        int rVal = 0;
        if (lField == null)
            if (rField == null) return 0;
            else return -1;
        rVal = lField.CompareTo(rField);
        return (_reverse) ? -rVal : rVal;
    }
}

使用通用比較器

此通用比較器對任何標記 DefaultSort 的 Customers 集合可排序:

CustomerList.Sort(new GenericComparer(typeof(Customer)));

GenericComparer 程式碼利用進階技術、反射(原則 43)。但只寫一次。之後只需添加特性到其他類別,即可對這些物件集合進行有用排序。修改 DefaultSort 參數即修改類別行為,無需修改所有演算法。

宣告式習慣的威力

當簡單宣告能說明意圖時,宣告式習慣很有用,幫助避免重複程式碼。參考 GenericComparer,你應能為任何建立的型別寫出不同(直接了當)的排序演算法。宣告式程式設計好處:只寫一次通用型別,再用簡單宣告為每個型別建立行為。關鍵:行為改變基於單一宣告,非基於演算法。GenericComparer 可在任何用 DefaultSort 修飾的型別上工作。若程式只需一兩次排序,按常規簡單方法寫。但若對同樣行為需在幾十個型別上實作,通用演算法與宣告式方案省下大量時間,長期運行也有力。不應為 WebMethod 特性寫所有程式碼,應將此技術展開在自有演算法上。原則 42 討論用特性建立附加命令處理常式。其他例子可能包括定義附加套件建立動態 Web UI 頁面。

總結

宣告式程式設計是強大工具,當可用特性表明意圖時,可減少大量類似手寫演算法中邏輯錯誤可能。建立更易讀、清晰程式碼,意味著現在或未來少出錯。若可用 .NET 框架定義特性,直接用。否則考慮建立自有特性,未來用它建立相同行為。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved