程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則24:選擇申明式編程而不是命令式編程(2)

Effective C#原則24:選擇申明式編程而不是命令式編程(2)

編輯:關於C語言

同樣,你還必須寫一些代碼,來對一個集合運行排 序,而該集合中的元素是添加了DefaultSort特性的對象。你將用到反射來發現 正確的屬性,然後比較兩個不同對象的屬性值。一個好消息是你只用寫一次這樣 的代碼。

下一步,你要寫一個實現了IComparer接口的類。(在原則26中 會詳細的充分討論比較。) ICompare有一個CompareTo()方法來比較兩個給定類 型的對象,把特性放在實現了IComparable的類上,就可以定義排序順序了。構 造函數對於通用的比較,可以發現默認的排序屬性標記,而這個標記是基於已經 比較過的類型。Compare方法對任何類型的兩個對象進行排序,使用默認的排序 屬性:

internal class GenericComparer : IComparer
{
 // Information about the default property:
 private readonly PropertyDescriptor _sortProp;
 // Ascending or descending.
 private readonly bool _reverse = false;
 // Construct for a type
 public GenericComparer( Type t ) :
   this( t, false )
 {
 }
 // Construct for a type
 // and a direction
 public GenericComparer( Type t, bool reverse )
 {
  _reverse = reverse;
  // find the attribute,
  // and the name of the sort property:
  // Get the default sort attributes on the type:
  object [] a = t.GetCustomAttributes(
   typeof( DefaultSortAttribute ),false );
  // Get the PropertyDescriptor for that property:
   if ( a.Length > 0 )
  {
   DefaultSortAttribute sortName = a[ 0 ] as  DefaultSortAttribute;
   string name = sortName.Name;
   // Initialize the sort property:
    PropertyDescriptorCollection props =
     TypeDescriptor.GetPropertIEs( t );
   if ( props.Count > 0 )
   {
    foreach ( PropertyDescriptor p in props )
    {
     if ( p.Name == name )
      {
      // Found the default sort property:
       _sortProp = p;
      break;
     }
     }
   }
  }
 }
 // Compare method.
  int IComparer.Compare( object left,
  object right )
  {
  // null is less than any real object:
  if (( left == null ) && ( right == null ))
   return 0;
   if ( left == null )
   return -1;
  if ( right == null )
   return 1;
  if ( _sortProp == null )
  {
   return 0;
  }
  // Get the sort property from each object:
  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;
 }
}

這個通用的比較 對任何Customers 集合可以進行排序,而這個Customers是用DefaultSort特性申 明了的:

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

實現GenericComparer的代碼利用了一些 高級的技術,使用反射(參見原則43)。但你必須寫一遍這樣的代碼。從這個觀點 上看,你所要做的就是添加空上屬性到其它任何類上,然而你就可以對這些對象 的集合進行能用的排序了。如果你修改了DefaultSort特性的參數,你就要修改 類的行為。而不用修改所有的算法。

這種申明式習慣是很有用的,當一 個簡單的申明可以說明你的意圖時,它可以幫助你避免重復的代碼。再參考 GenericComparer類,你應該可以為你創建的任何類型,寫一個不同的(而且是是 直接了當的)排序算法。這種申明式編程的好處就是你只用寫一次能用的類型, 然後就可以用一個簡單的申明為每個類型創建行為。關鍵是行為的改變是基於單 個申明的,不是基於任何算法的。GenericComparer可以在任何用DefaultSort特 性修飾了的類型上工作,如果你只須要在程序裡使用一兩次排序功能,就按常規 簡單的方法寫吧。然而,如果你的程序對於同樣的行為,可能須要在幾十個類型 上實現,那麼能用的算法以及申明式的解決方案會省下很多時間,而且在長時間 的運行中也是很有力的。你不應該為WebMethod特性寫代全部的代碼,你應該把 這一技術展開在你自己的算法上。原則42裡討論了一個例子:如何使用特性來建 立一個附加命令句柄。其它的例子可能還包括一些在定義附加包建立動態的web UI面頁時的其它內容。

申明式編程是一個很有力的工具,當你可以使用 特性來表明你的意圖時,你可以通過使用特性,來減少在大量類似的手寫算法中 出現邏輯錯誤的可能。申明式編程創建了更易於閱讀,清晰的代碼。這也就意味 著不管是現在還是將來,都會少出現錯誤。如果你可以使用.Net框架裡定義的特 性,那就直接使用。如果不能,考慮選擇創建你自己的特性,這樣你可以在將來 使用它來創建同樣的行為。

返回教程目錄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved