3

C# でテンプレートを使用する方法を理解しようとしています。私はこれを書きました:

public static List<TValue> deepCopyList<TValue>(List<TValue> src)
{
    List<TValue> arr = new List<TValue>();

    for (int i = 0; i < src.Count; i++)
    {
        arr.Add(new TValue(src[i]));   //Error on this line
    }

    return arr;
}

しかし、私はエラーが発生します:

エラー CS0304: new() 制約がないため、変数型 'TValue' のインスタンスを作成できません

4

5 に答える 5

2

ここでの問題は、パラメーターを指定してコンストラクターを呼び出しているため、new制約が十分でないことです。できることは、次のようにコンストラクターを動的に呼び出すことです (TValue クラスに一致するコンストラクターがあることを確認する必要があります)。

public static List<TValue> DeepCopyList<TValue>(List<TValue> values)
{
    List<TValue> list = new List<TValue>();
    var ctor = typeof(TValue).GetConstructor(new[] {typeof(TValue)});
    foreach (TValue value in values)
    {
        list.Add((TValue)ctor.Invoke(new object[] {value}));
    }
    return list; 
}

またはlinqで:

public static List<TValue> DeepCopyList<TValue>(List<TValue> values)
{
    return (from value in values 
      let ctor = typeof(TValue).GetConstructor(new[] {typeof(TValue)}) 
      select (TValue)ctor.Invoke(new object[] {value})).ToList();
}

使用例:

public class Test
{
    public Test(Test test)
    {
        // Do what you want...
    }
}

List<Test> tests = new List<Test>() { new Test(null) };
List<Test> results = DeepCopyList(tests);  


それ以外の場合は、このリンクも役立つ場合があります: Passing arguments to C# generic new() of templated type

于 2013-05-24T08:57:54.397 に答える
1

ジェネリック引数で演算子を使用する場合はnew、次のように、型引数にデフォルトのコンストラクターが必要であることを指定する必要があります。

public static List<T> deepCopyList<T>(List<T> src)
    where T : new()
{
    // I can now call new, like so
    var value = new T();
}

ただし、元のオブジェクトのコピーがないため、これだけではあまり役に立ちません。新しいオブジェクトがあるだけです。残念ながら、型が特定のコンストラクターをサポートする必要があることを指定できないため、コピーコンストラクターなどを呼び出します。

私がおそらくすることはこれです

public static List<T> deepCopyList<T>(List<T> src)
    where T : ICloneable
{
    var value = src[0].Clone();
}

これは、このメソッドを をサポートする型でのみ使用できることを意味しますがICloneable、リフレクションやその他のトリックの使用に戻らなくても、おそらくこれで十分です。

于 2013-05-24T09:03:50.157 に答える
0

メソッドの署名は次のようになります。

public static List<TValue> deepCopyList<TValue>(List<TValue> src) where TValue : new()

ただし、オブジェクトの初期化を空のコンストラクターを持つように変更し、後でプロパティを設定する必要がある場合があります。

TValue val = new TValue();
val.MyField = src[i]; // This only works if you further constrain the type of TValue
arr.Add(val);

新しい制約に関する公式ドキュメントも参照してください。

于 2013-05-24T08:53:46.953 に答える
-1

コンパイラは、where 制約で明示的に指定しない限り、ジェネリック型を new でインスタンス化できることを知りません。

于 2013-05-24T08:48:11.223 に答える