1
new List<BaseType>
{
    new DerivedType
    {
        x="x1",y="y1",z="z1"
    },
    new DerivedType
    {
        x="x2",y="y2",z="z2"
    },
    new DerivedType
    {
        x="x3",y="y3",z="z3"
    },
    new DerivedType
    {
        x="x4",y="y4",z="z3"
    },
    ...
}

静的メソッドでは、上記のメソッドを介してリストが初期化されますが、これを構文的に行うためのより良い方法があるかどうか疑問に思っていました。

簡単にするために、同じフィールドが毎回同じ順序で設定されています。

4

6 に答える 6

8

ここで for ループを使用しないのはなぜですか?

var list = new List<BaseType>(SomeValue);
for (int i = 1; i < SomeValue; i++) { 
  list.Add(new DerivedType {
    x = string.Format("x{0}", i),
    y = string.Format("y{0}", i),
    z = string.Format("z{0}", i)
  });
}

注: サンプル コードの最後の init は、"z4"代わりに"z3"

于 2013-03-15T21:58:48.103 に答える
5

値が実際に「x1」などの場合、次のようにします。

var list = Enumerable.Range(1, n)
                     .Select(i => new DerivedType {
                                 x = "x" + i,
                                 y = "y" + i,
                                 z = "z" + i
                             })
                     .ToList<BaseType>();

これは、C# 4 の共分散に依存しています。C# 3 (または .NET 3.5 を対象とする) では、次のようなものが必要になります。

var list = Enumerable.Range(1, n)
                     .Select(i => (BaseType) new DerivedType {
                                 x = "x" + i,
                                 y = "y" + i,
                                 z = "z" + i
                             })
                     .ToList();

または、それらが単なるサンプル値である場合 (またはそうでない場合でも)、コンストラクターを追加してDerivedType、3 つのプロパティを一度に渡すことができるようにするだけで、煩雑さが軽減されます。

new List<BaseType>
{
    new DerivedType("x1", "y1", "z1"),
    new DerivedType("x2", "y2", "z2"),
    new DerivedType("x3", "y3", "z3"),
    new DerivedType("x4", "y4", "z4"),
    ...
}
于 2013-03-15T22:01:34.640 に答える
2

次のサブクラスを作成できますList<T>

public class BaseTypeList : List<BaseType>
{
    public void Add(string x, string y, string z)
    {
        Add(new DerivedType { x = x, y = y, z = z });
    }
}

次に、コレクション初期化構文をより簡潔に使用できます。

new BaseTypeList
{
    { "x1", "y1", "z1" },
    { "x2", "y2", "z2" },
    { "x3", "y3", "z3" },
    { "x4", "y4", "z3" /* (sic) */ },
    //...
}

これが機能するのは、コンパイラがコレクション初期化ブロックの要素ごとに個別のオーバーロード解決を実行し、指定された引数に一致するパラメータタイプを持つAddメソッドを探すためです。

同種の派生型が必要な場合、少し醜くなりますが、それは可能です。

public class BaseTypeList : List<BaseType>
{
    public void Add(Type t, string x, string y, string z)
    {
        Add((BaseType)Activator.CreateInstance(t, x, y, z));
    }
}

次に、次のようにコレクションを初期化します。

new BaseTypeList
{
    { typeof(DerivedType1), "x1", "y1", "z1" },
    { typeof(DerivedType1), "x2", "y2", "z2" },
    { typeof(DerivedType2), "x3", "y3", "z3" },
    { typeof(DerivedType2), "x4", "y4", "z3" /* (sic) */ },
    //...
}
于 2013-03-16T01:18:28.407 に答える
1

OPのより一般的な質問に誰も取り組んでおらず、例の考案された特殊なケースに焦点を合わせているのは奇妙だと思います。

ここですべてのヘビーヒッターが気づいたように、この例の特定のケースでは、Perlの禁欲主義者が言うように、「TMTOWTDI」—それを行うには複数の方法があります。他のものよりも優れている(または少なくともより簡潔な)ものもあります。

物事がすべて単調なシーケンスではない、より一般的なケースでは、これ以上良いものはないと思います。あなたは多くの反復的な定型文で立ち往生しています。

C#には、JSONやJavascriptのオブジェクト初期化子、またはCの複合リテラル(2000年にC99で導入された)のようなものはありません。これらはすべて、この種のものに対してはるかに簡潔な構文を提供します。あなたが私に尋ねれば、残念です。

少し醜いハックですが、ここに1つの考えがあります。SCG.List<T>他の多くのコレクションには、構築中のオブジェクトが読み込まれる、、または同様のものSCGを受け入れるコンストラクターのオーバーロードがあります。おそらく、アセンブリに必要なデータを、目的に適した形式の埋め込みリソースとして埋め込むことができます。埋め込みリソースである必要はありません。アイテムごとに1行のコンマ区切りの単純な複数行の文字列リテラルでうまくいきます。そのリソースを使用して、コンストラクターとBob's-Yer-Uncleに渡すことができるウィジェットのLINQyストリームを生成する単純なファクトリクラスまたはメソッドを提供します。IEnumerable<T>IDictionary<TKey,TValue>IEnumerableList<T>

私が言ったように、少し醜いハックですが、それは繰り返しのタイピングを避けます。

于 2013-03-15T23:52:20.097 に答える
1

NBuilderでは、1 行または 2 行のコードが必要です (NuGet から取得できます)。

List<BaseType> list = Builder<DerivedType>.CreateListOfSize(5).Build()
                                          .ToList<BaseType>();

すべてのプロパティを値"xN" "yN" "zN"(プロパティ名 + 要素インデックス) で初期化します。

于 2013-03-15T22:03:28.597 に答える
0

データを保持するために単純な配列を使用します。次に、この配列を使用して派生型を構築します。データ値は多少任意であることに注意してください (ここでは string 型と int 型を示しています)。これは、文字列の配列を使用するだけで、元の質問に対して最適化できます。

object[] data = 
{
    "x1", "y1", 4,
    "x2", "y2", 3,
    "x3", "y3", 2,
    "x4", "y4", 3
};

int countPerType = 3;
int size = data.Length;

var initMe = new List<BaseType>();

for (int idx = 0; idx < size; idx += countPerType)
{
    initMe.Add(
        new DerivedType() 
        { 
            X = (string)data[idx], 
            Y = (string)data[idx + 1], 
            Z = (int)data[idx + 2] 
        });
}
于 2013-03-15T22:57:03.710 に答える