2013-07-21 169 views
6

而不是重載一個函數100次或爲不同的類型創建100個不同的比較器我決定檢查一個函數內的類型。什麼是檢查類型的最快方法?

例如,我使用默認比較器來比較2個對象中的一組類型(基元和字符串)的值。它包含以下代碼:

public class DefComparer : IComparer<object> { 
    public int Compare(object a, object b) { 
     .... // a = a.GetType().GetField(field).GetValue(a); - not important for the question but I'm just showing that a&b below are different references 
     switch (a.GetType().Name) { 
      case "Byte": 
       if ((byte)a == (byte)b) return 0; 
       else if ((byte)a > (byte)b) return 1; 
       else return -1; 
      case "UInt16": 
       if ((ushort)a == (ushort)b) return 0; 
       else if ((ushort)a > (ushort)b) return 1; 
       else return -1; 
      case "SByte": 
       if ((sbyte)a == (sbyte)b) return 0; 
       else if ((sbyte)a > (sbyte)b) return 1; 
       else return -1; 
      case "Int16": 
       ... 

這裏我使用的是switch聲明被認爲是比if/else語句鏈更快。但a.GetType().Name返回一個動態獲取的字符串,此方法涉及字符串比較。這聽起來並不特別快。我需要比較器的速度儘可能快,因爲它將用於大量的數據集合。

問:有沒有更快的方法來檢查對象的類型(不涉及字符串比較)?什麼是最快的方法?

+1

您正在尋找'Comparer.Default'。 – SLaks

+0

或者調用((IComparable)a).CompareTo(b) – usr

+0

不,我不是在尋找'Comparer.Default'。我編輯了我的帖子,使其更加清晰。我的問題是關於檢查類型的快速方法。 – brandon

回答

6

那麼你有它在你的手中。使用TypeCode

 int a = 10; 
     Type t = a.GetType(); 

     switch (Type.GetTypeCode(t)) 
     { 
      case TypeCode.Boolean: 
       break; 
      case TypeCode.Byte: 
       break; 
      case TypeCode.Char: 
       break; 
      case TypeCode.DBNull: 
       break; 
      case TypeCode.DateTime: 
       break; 
      case TypeCode.Decimal: 
       break; 
      case TypeCode.Double: 
       break; 
      case TypeCode.Empty: 
       break; 
      case TypeCode.Int16: 
       break; 
      case TypeCode.Int32: 
       break; 
      case TypeCode.Int64: 
       break; 
      case TypeCode.Object: 
       break; 
      case TypeCode.SByte: 
       break; 
      case TypeCode.Single: 
       break; 
      case TypeCode.String: 
       break; 
      case TypeCode.UInt16: 
       break; 
      case TypeCode.UInt32: 
       break; 
      case TypeCode.UInt64: 
       break; 
      default: 
       break; 
     } 

這支持所有原語。自定義對象在TypeCode.Object中寫入else if語句。

我希望這會有所幫助。

+0

是的,測試表明你的方法更快。我不知道'TypeCode'枚舉。 – brandon

+0

@brandon歡呼,現在你知道了。 –

+0

@brandon我建議你投到適當的類型,並將其存儲在本地變量,然後比較性能而不是「拆箱」兩次 –

3

從評論中,聽起來好像你有一堆結構化數據,其中有不同類型的子對象。

如果集合很大,最快的方法是動態代碼生成器(可能有表達式樹)來創建一個方法,以強類型方式提取所有感興趣的字段/屬性,並執行強類型比較。

基本上,您使用反射來從集合成員類型動態獲取字段/屬性類型。然後建立MemberAccessExpression表達式,將其傳遞給Expression.Equal,並將所有結果傳遞給Expression.AndAlso。編譯表達式將爲您提供一個委託,它包含集合中包含的特定類型的兩個對象。

啓動時間將比您在問題中顯示的代碼慢兩個數量級,但每個對象的成本會降低很多。你必須進行測試,看看盈虧平衡點在哪裏 - 但可能在幾千美元。

相關問題