2011-07-09 18 views
1

私は、クラスのインスタンスの数が多いしたいが、この実装例のように、同じデータの類似のフィールドを返す:私は好きではない何C#邪悪な高速配列検索?

foreach (SomeClass sc in SomeClasses) 
{ 
    System.Console.WriteLine(sc.GetData("1st field")); 
    System.Console.WriteLine(sc.GetData("Another field")); 
    System.Console.WriteLine(sc.GetData("and another")); 
} 

// ---- inside SomeClass: 

Dictionary<string, string> myData; 

public string GetData(string field) 
{ 
    return myData[field]; 
} 

はしていた文字列のハッシュ、検索とマッチングですこの例で何度も何度も何度も何度も何度も何度も何度も何度も何度も何度も何度もやっています私は本当に良いアプローチを探しています。 Cの世界から来る

は、私は、配列の参照に変更することができるように、すべてのフィールドにユニークな整数キーを割り当てることを考えた:

// ---- inside SomeClass: 

string[] MyData; 

public string GetData(int field_key) 
{ 
    return MyData[field_key]; 
} 

今すぐフィールド検索が効率的であるが、それはちょうどdoesnの」これらの「配列は悪い」時代に感じることがあり、退屈で、field_key整数を処理するのは誤りです。

ここでパフォーマンスの幽霊を追いかけているのかどうかは分かりません。効率的でクリーンなデザインを見つけたいと思っています。

提案?

答えて

2

フィールドはコンパイル時にはわかりませんが、動的でユーザーが設定できるので、サンプルプログラムを少し変更してプロパティの配列を使用します。それから、あなたと似たアプローチを提唱しますが、文字列ではなく独自のカスタムクラス(ここではMyPropertyと呼んでいます)を使用します。パフォーマンスは、少なくとも文字列アプローチと同じくらい良いでしょうが、多分より良い結果が得られますが、利点は、より柔軟性があるということです。パフォーマンスの理由から最終的に配列やリスト手法を使用する必要がある場合は、 MyPropertyクラスに配列インデックスを簡単に埋め込むことができます。 GetDataの実装を変更する必要がありますが、呼び出しコードは変更しないでください。ターゲットアプリケーションは、本当にダイナミックでユーザー設定可能なプロパティのゲッターのセットを集める程度であるので、

public static void Test1() { 
    SomeClass[] SomeClasses; //created somehow 

    //in real life, this would be determined dynamically 
    var properties=new[] {SomeClass.FirstField, SomeClass.AnotherField, SomeClass.AndAnother}; 

    foreach(var sc in SomeClasses) { 
    foreach(var property in properties) { 
     Console.WriteLine(sc.GetData(property)); 
    } 
    } 
} 

public class SomeClass { 
    public static readonly MyProperty FirstField=new MyProperty(); 
    public static readonly MyProperty AnotherField=new MyProperty(); 
    public static readonly MyProperty AndAnother=new MyProperty(); 

    private readonly Dictionary<MyProperty, string> myData=new Dictionary<MyProperty, string>(); 

    public string GetData(MyProperty property) { 
    return myData[property]; 
    } 
} 

//default implementation of Equals and GetHashCode are fine here 
public class MyProperty {} 

しかし、多分あなたは本当にいくつかのfuncsを作りたいですか?以下のようなコードは非常に速く、それでもあなたが望む能力を持っています。つまり、ユーザーが設定できる小さなゲッターのリストを作ることができます。

public static void Test2() { 
    SomeClass[] SomeClasses; //created somehow 

    //in real life, this would be determined dynamically 
    var getters=new[] {SomeClass.FirstField, SomeClass.AnotherField, SomeClass.AndAnother}; 
    foreach(var sc in SomeClasses) { 
    foreach(var getter in getters) { 
     System.Console.WriteLine(getter(sc)); 
    } 
    } 
} 

public class SomeClass { 
    public static readonly Func<SomeClass, string> FirstField=sc => sc.field0; 
    public static readonly Func<SomeClass, string> AnotherField=sc => sc.field1; 
    public static readonly Func<SomeClass, string> AndAnother=sc => sc.field2; 

    private string field0; 
    private string field1; 
    private string field2; 
} 
+0

返信とコード例ありがとう。私はフィールド/プロパティを表すクラスを持っていますが、問題に遭遇することなく辞書参照のためにそのクラスのインスタンスを使用できるかどうか疑問に思っていました。 funcの解決策は、私には起こりませんでした、非常に啓発、ありがとう!私にとって、これは実際の問題を解決することと同じくらいC#を学ぶことです。 – Larsp

4

なぜ辞書を検索したくないのですか?辞書の非常に効率的な実装は、配列内のハッシュのインデックスルックアップである。したがって、基本的な実装は、2番目の例のコードに沸騰する可能性があります。これはなるだろう、それO(1)

、なぜ単にプロパティを使用しないで、あなたのインスタンスが同じフィールドを持っている場合は辞書

+0

ええ、私は辞書に整数キーをルックアップさせることができます。私はそれが解決策になると思います。 – Larsp

+0

質問:フィールドはクラスでも表されます。辞書にこのクラスのオブジェクトをルックアップさせることは可能ですか? – Larsp

+0

@Larspここに問題があります。経験則は決して事前に最適化しないことです。プロファイラを使用してコードを実行すると、いくつかの無料のものもあります。あなたは、アプリケーションをプロファイルするまで、幽霊を追跡しています。辞書は効率的です。 –

2

を使用しますか?あなたがわからない場合

foreach (SomeClass sc in SomeClasses) 
{ 
    System.Console.WriteLine(sc.FirstField); 
    System.Console.WriteLine(sc.AnotherField); 
    System.Console.WriteLine(sc.AndAnother); 
} 
+0

フィールドはコンパイル時には分かりません。これらは動的でユーザーが設定できます。 – Larsp

1

まず、これは実際にあなたのためのパフォーマンスの問題があり、[はい、あなたが追いかけているパフォーマンスの幽霊とあなたの現在の実装で結構です。

しかし、プロファイリング中にこのコードをもっと速くする必要があることが判明した場合は、うまくいくように見えます。 "Arrays are evil"は、パブリックインターフェイスでのみ真実ですが、実装に使用するとうまくいきます。

私はあなたのコードについて変更することが1つです:フィールドを含むenumを作成し、intの代わりに使用します。それは、速くてはるかに読みやすくなります。コンパイル時にフィールドがわからない場合は、intを使用しても問題ありません。コンパイル時にフィールドのいくつかを知っていれば、静的プロパティを使用することができます。

+0

実際には、非動的なフィールドの列挙型を作成しましたが、コンパイラが列挙型のメンバーをint型にキャストして配列を検索する前に悩まされていました。 – Larsp

+0

@Larsp:うん、うんざりです。あなたはパブリック定数の束で静的クラスを作ることができますが、コンパイラは衝突をチェックしません。これには完璧な答えはありません。 (私は、コードジェネレータが識別子の単純なリストから 'int'型でオーバーラップせずに定数を作成できると思うが、それはビルドプロセスをより複雑にする) –

+0

公共の定数を持つ静的クラスは、先端。 – Larsp