2013-07-21 24 views
6

関数を100回オーバーロードするか、異なるタイプのCompareerを100個作成するのではなく、1つの関数内で型をチェックすることにしました。タイプをチェックする最も速い方法は何ですか?

たとえば、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": 
       ... 

ここで私はif/else文のチェーンよりも高速であると言われてswitch文を使用しています。しかし、a.GetType().Nameは動的に取得される文字列を返し、このメソッドは文字列の比較を含みます。それは私にとって特に速くは聞こえません。私はComparerが技術的に可能な限り高速であることが必要です。なぜなら、それは大量のデータのコレクションで使用されるからです。

Q:文字列比較を含まないオブジェクトの種類を確認する方法はありますか?最速の方法は何ですか?

+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; 
     } 

これはすべてのプリミティブをサポートします。カスタムオブジェクト用else ifステートメントをTypeCode.Objectに書き込んでください。

こちらがお役に立てば幸いです。

+0

はい、テストはあなたの方法がより速いことを示します。私は 'TypeCode' enumについて知らなかった。 – brandon

+0

@brandonがうれしく思います。 –

+0

@brandon適切な型にキャストし、ローカル変数に格納して、 'Unboxing'の代わりにパフォーマンスを比較することをお勧めします。 –

3

コメントからは、さまざまなタイプのサブオブジェクトを持つ構造化データがあるかのように見えます。

コレクションが大きい場合、最も速い方法は、強く型付けされた方法で関心のあるすべてのフィールド/プロパティをプルし、強く型付けされた比較を実行する単一のメソッドを作成する動的なcodegen(おそらく式ツリー)です。

基本的に、リフレクションを使用してコレクションメンバータイプからフィールド/プロパティタイプを動的に取得します。次に、MemberAccessExpression式を作成し、それらをExpression.Equalに渡し、すべての結果をExpression.AndAlsoに渡します。式をコンパイルすると、コレクションに含まれる特定の型の2つのオブジェクトを取る代理人が得られます。

スタートアップ時間は、質問に表示されたコードよりも数桁遅くなりますが、オブジェクトあたりのコストは大幅に低くなります。損益分岐点はどこにあるのかを調べるためにテストしなければならないでしょうが、おそらく低水準です。

関連する問題