11

基本的にルックアップテーブルである大きな静的リストがあるので、コードでテーブルを初期化します。

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
}

これは可能ですか?KeyValuePairこのようにaの'をDictionary<>初期化できるからだと思います。

MSDNの状態:

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

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

4

5 に答える 5

15

Listの代わりにカスタムコレクションを作成する必要があると思います。たとえば、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 }
};

私は今上記のコードを試しました、そしてそれは私のために働くようです。

于 2012-02-08T13:42:42.090 に答える
6

クイックフィックス:複数の引数を取るオーバーロードを使用して独自のList型を作成します。Add

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

より基本的な答え:

オブジェクト初期化子コレクション初期化子を混同しています。簡単に言えば:

オブジェクト初期化子は構文上のトリックであり、バックグラウンドで、指定された値を使用して、名前付きプロパティごとにプロパティセットメソッドを呼び出します。

コレクション初期化子は、バックグラウンドで次のような構文上のトリックです。

  • タイプの場合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);
    }
}

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

于 2012-02-08T14:23:04.027 に答える
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 },
}

Addしたがって、に4つのパラメータがあるメソッドを探していますがList<T>、それは存在しません。

カスタムコレクション初期化子を使用するには、独自のコレクションクラスを実装する必要があります。を使用している間List<T>、あなたはあなたが持っているコンストラクター呼び出しで立ち往生しています。

于 2012-02-08T13:42:39.220 に答える
1

List <LookupItem>から派生したカスタムクラスでListの意図を曖昧にするのではなく、必要なコンストラクターを呼び出す単純な拡張機能を追加します。

public static class LookupItemListExtensions
{
    public static void Add(this List<LookupItem> lookupItemList, int param1, int param2, float param3, float param4)
    {
        lookupItemList.Add(new LookupItem(param1, param2, param3, param4));
    }
}

簡潔さと明快さを交換していることに注意してください。自己責任で使用してください。「newListItem」を使用すると、コンストラクターに直接F12できます。この拡張機能はそうではありません(他の開発者にとっては明らかではないでしょう)。

于 2019-01-02T20:06:27.263 に答える
0

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

いいえ、それはをList<LookupItem>実装することを意味しますIEnumerable、それがあなたが書くことができる理由です

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

LookupItemまた、あなたが実装したコレクションである場合、次のIEnumerableように書くことができた可能性があることも意味します。

private static List<LookupItem> _lookupTable = new List<LookupItem>()
{ 
    new LookupItem { new Item(), new Item() },
    new LookupItem { new Item(), new Item() }
}
于 2012-02-08T13:46:09.640 に答える