2012-02-08 7 views
8

私は基本的にルックアップテーブルである大きな静的リストを持っているので、私はコードでテーブルを初期化します。カスタム・タイプでのコレクション初期化構文の使用

private class MyClass 
{ 
    private class LookupItem 
    { 
     public int Param1 { get; set; } 
     public int Param2 { get; set; } 
     public float Param2 { get; set; } 
     public float Param4 { get; set; } 
    } 

    private static List<LookupItem> _lookupTable = new List<LookupItem>() 
    { 
     new LookupItem() { Param1 = 1, Param2 = 2, Param3 = 3 Param4 = 4 }, 
     new LookupItem() { Param1 = 5, Param2 = 6, Param3 = 7 Param4 = 8 }, 
     //etc 
    } 
} 

本当LookupItemは、より多くの特性を有しているので、私はよりコンパクトな初期化形式を可能にするためにコンストラクタを追加しました:

private class MyClass 
{ 
    private class LookupItem 
    { 
     public int Param1 { get; set; } 
     public int Param2 { get; set; } 
     public float Param2 { get; set; } 
     public float Param4 { get; set; } 

     public LookupItem(int param1, int param2, float param3, float param4) 
     { 
      Param1 = param1; 
      Param2 = param2; 
      Param3 = param3; 
      Param4 = param4;  
     } 
    } 

    private static List<LookupItem> _lookupTable = new List<LookupItem>() 
    { 
     new LookupItem(1, 2, 3, 4), 
     new LookupItem(5, 6, 7, 8), 
     //etc 
    } 
} 

は、私が本当にしたいことはフォーマット初期化子コレクションを使用していますオブジェクト自体のために私はすべての行にnew LookupItem()を取り除くことができます。例:

private static List<LookupItem> _lookupTable = new List<LookupItem>() 
{ 
    { 1, 2, 3, 4 }, 
    { 5, 6, 7, 8 }, 
    //etc 
} 

これは可能ですか?私はそれがDictionary<>KeyValuePairがこのように初期化できるのでそれが思うのが好きです。

MSDN国は:

コレクション初期化子は、あなたが IEnumerableをを実装コレクションクラスを初期化する際に使用すると、1つまたは複数の要素 intializersを指定できます。要素イニシャライザは、簡単な値、 式またはオブジェクト初期化子にすることができます。コレクション初期化子 を使用すると、ソースコード内の クラスのAddメソッドへの複数の呼び出しを指定する必要はありません。コンパイラは呼び出しを追加します。

LookupItemクラスにIEnumerableを実装して各パラメータを返す必要があるのですか?私のクラスはコレクションクラスではありません。

答えて

11

リストの代わりにカスタムコレクションを作成する必要があると思います。例えば、LookupItemTableと呼んでください。そのコレクションにAdd(int、int、float、float)メソ​​ッドを与え、IEnumerableを実装します。例:

class LookupItem 
{ 
    public int a; 
    public int b; 
    public float c; 
    public float d; 
} 

class LookupItemTable : List<LookupItem> 
{ 
    public void Add(int a, int b, float c, float d) 
    { 
     LookupItem item = new LookupItem(); 
     item.a = a; 
     item.b = b; 
     item.c = c; 
     item.d = d; 
     Add(item); 
    } 
} 

private static LookupItemTable _lookupTable = new LookupItemTable { 
    { 1, 2, 3, 4 }, 
    { 5, 6, 7, 8 } 
}; 

私は今、上記のコードを試してみたところ、私にとってはうまくいくようです。

+0

素晴らしい。どうもありがとうございました。 – GazTheDestroyer

4

あなたはリスト自体ではなく、あなたのタイプにコレクション初期化子を使用しようとしている:

// Note the "new List<...>" part - that specifies what type the collection 
// initializer looks at... 
private static List<LookupItem> _lookupTable = new List<LookupItem>() 
{ 
    { 1, 2, 3, 4 }, 
    { 5, 6, 7, 8 }, 
} 

だから、List<T>の4つのパラメータでAdd方法を探している、それは存在しません。

カスタムコレクション初期化子を使用するには、コレクションクラスを実装する必要があります。 List<T>を使用している間は、あなたはコンストラクタの呼び出しに悩まされています。

0

これは、LookupItemクラス にIEnumerableを実装して各パラメータを返す必要があることを意味しますか?私のクラスはコレクションクラスではありません。

はありません、それはList<LookupItem>はあなたがそれはまたあなたのLookupItemIEnumerableを実装し、コレクションだった場合、あなたが書かれていることを意味

private static List<LookupItem> _lookupTable = new List<LookupItem>() 
{ 
    new LookupItem(1, 2, 3, 4), 
    new LookupItem(5, 6, 7, 8), 
    //etc 
} 

を書くことができる理由である、IEnumerableを実装していることを意味し

private static List<LookupItem> _lookupTable = new List<LookupItem>() 
{ 
    new LookupItem { new Item(), new Item() }, 
    new LookupItem { new Item(), new Item() } 
} 
5

クイックフィックス:自分でListタイプを複数の引数を取りますオーバーロード:

class LookupList : List<LookupItem> { 
    public void Add(int Param1, int Param2, ... sometype ParamX) { 
     this.Add(new LookupItem() { Param1 = Param1, Param2 = Param2, ... ParamX = ParamX }); 
    } 
} 

は今、あなたが望むとおりに動作します:

private static LookupList _lookupTable = new LookupList() {     
     {1,2,3,4},     
     {2,7,6,3}     
    }; 

はもっと根本的な答え:

あなたはobject initializersを混合し、collection initializersています。

オブジェクトイニシャライザは、バックグラウンドで指定された値を持つ各名前付きプロパティのプロパティセットメソッドを呼び出すシンタックストリックです。 Arrayタイプの場合

  • IEnumerableを実装しなければならない項目の任意の他のタイプのために
  • 、との配列を入力します。

    コレクション初期化子は、バックグラウンドで、構文上のトリックですコールサブブラケットセットごとにAddメソッド。

すべてがあります。例えば、以下のハックを考えてみましょう。

public class Hack : IEnumerable { 
    public int LuckyNumber { get; set; } 
    public double Total { get; private set; } 
    public void Add(string message, int operand1, double operand2, double operand3) { 
     Console.WriteLine(message); 
     this.Total += operand1 * operand2 - operand3; 
    } 
    public IEnumerator GetEnumerator() { throw new NotImplementedException(); } 
} 

class Program { 
    static void Main(string[] args) { 
     Hack h1 = new Hack() { 
      { "Hello", 1, 3, 2}, 
      { "World", 2, 7, 2.9} 
     }; 
     Console.WriteLine(h1.Total); 
     Hack h2 = new Hack() { LuckyNumber = 42 }; 
     Console.WriteLine(h2.LuckyNumber); 
    } 
} 

あなたは実際のプログラムでこれを行うべきではありませんが、私はこの例を調べ、その結果を願って、あなたはそれをステップデバッグする場合は特に、あなたは明確に初期化子を理解するのに役立ちますし、現在のシナリオに適したソリューションを選択してください。

+0

'あなたは本当のプログラムでこれを行うべきではありません.' - 大丈夫です。実際のプログラムではどうしたらいいですか?シナリオ:Javaから移植し、3つの 'Add()'オーバーロードを持ち、 'IEnumerable 'を実装しているクラスがあります。もし私が 'ICollection 'を実装しているのであれば、私は、不要な(不要な)Remove()、Clear()メソッドを用意しています。 Intellisenseを使用してコレクションイニシャライザを使用する方法を明確にする別の解決法があるのですか、ドキュメントを私の唯一の選択肢として書いていますか? – NightOwl888

関連する問題