5

皆さんに少し問題があります。

私はこれをしたいと思います:

Type[] classes = new Type[]{ Class1, Class2 };

foreach(Type t in classes){   
  List<t> list = new List<t>(); 
}

これを行う方法はありますか?

4

5 に答える 5

6

ジェネリックの型はコンパイル時に解決する必要があるため、実行時にジェネリック型にキャストすることはできません。

リフレクションを使用してジェネリック型を動的に作成できますが、キャストをハードコーディングしない限り、返されるのはオブジェクトだけです。

私はあなたが何を望んでいるのか本当にわかりません。コメントに同意する必要があります。これはXY の問題です。設計上の問題に直接対処したり、何を達成しようとしているのかを直接質問したりするのではなく、これが解決しようとしている設計上の問題がどこかにあるという傲慢な発言をする傾向があります。


次のコードを使用して型を作成すると、そのdynamic型を使用して、それがリストであることやそれが何であるかを認識/気にせずに、さまざまなメンバーをダック型にすることができます。List<T>T

using System;
using System.Collections.Generic;

namespace ConsoleApplication61
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic o = CreateGeneric(typeof(List<>), typeof(int));
            o.Add(1);
            Console.WriteLine(o[0]);
            Console.Read();
        }

        public static object CreateGeneric(Type generic, Type innerType, params object[] args)
        {
            System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
            return Activator.CreateInstance(specificType, args);
        }
    }
}

上記のサンプル ダックは、Addメソッドとインデクサーを型付けします。DLR は、実行時に型処理とダック タイピングを行います。たとえば、それ1が であることを認識しています。int

明確にするために、私はそのようなコードを本番環境で使用しない可能性が高く (これを必要とする要件が非常に具体的でない限り)、型の不一致に関する問題は実行時に発生します。そのため、非常に正確に入力するか (IntelliSense の制限あり)、適切なエラー処理を行う必要があります。

メソッドのこのブログ投稿に感謝しCreateGenericます。

これは、新しい CLR を使用した .NET 4 を想定しています。@MartinLiversage も指摘しているように、この特定のサンプルは、厳密に型指定された方法でリストを利用していることを前提としています。私の例では、intを a のList<int>非表示に渡していdynamicます。


私たちは、.NET 4 がリリースされてからずっと使用しています。さらに大きなコード ベースを持つ大規模なアプリケーションがあります。dynamicアプリケーションでは 1 回も使用されず、テスト コード ベースでは数回しか使用されません。それは「使わない」ということではなく、「ほとんどの場合、必要ない」ということです。

于 2012-05-25T12:19:36.370 に答える
5

次のように実行できます。

foreach(Type t in classes)
{
   var listType = typeof(List<>).MakeGenericType(t);
   var instance = Activator.CreateInstance(listType);
}
于 2012-05-25T12:13:01.973 に答える
2

これはType.MakeGenericType メソッドで可能です

これは、私が見つけた気の利いた方法で、うまくいくはずです:CodeRef

public static object CreateGeneric(Type generic, Type innerType, params object[] args)
{
    System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
    return Activator.CreateInstance(specificType, args);
}

そして、次のように使用します。

var o = CreateGeneric(typeof(List<>), t);

残念ながら、アイテムを追加するには、そのようにする必要があります (item は追加するアイテムです)。

MethodInfo addMethod = o.GetType().GetMethod("Add");
addMethod.Invoke(o, new object[] { item.ToType(t) });

またはGeneric、別の回答で言及されているタイプを使用します。

于 2012-05-25T12:12:48.850 に答える
1

これを試すことができます:

Type[] classes = new Type[] { typeof(A), typeof(B) };           
foreach (Type t in classes)
{
     Type genericType = typeof(List<>).MakeGenericType(t);
     var list = Activator.CreateInstance(genericType);
}
于 2012-05-25T12:21:14.057 に答える
1

オブジェクトを 1 つのリストにまとめたい場合は、おそらく共通点があります。

そのような場合、コメントでLBが言及したように、ここで間違った質問をしていると私は主張します.

おそらくそれはあなたが持っている設計上の問題です。これらの型について考え、それらの共通点を確認し、1 つの基本型から派生させるか、両方に同じインターフェイスを実装させるかを考えてください。このような場合、基本タイプ/インターフェースのオブジェクトのリストをインスタンス化し、それらを操作することができます。

有利なスタートを切るために:

    abstract class Vehicle {
        public int NumberOfWheels { get; set; }
    }

    class Car : Vehicle
    {
        public Car()
        {
            NumberOfWheels = 4;
        }
    }

    class Bicycle : Vehicle
    {
        public Bicycle()
        {
            NumberOfWheels = 2;
        }
    }

    static void Main(string[] args)
    {

        var v1 = new Car();
        var v2 = new Bicycle();

        var list = new List<Vehicle>();
        list.Add(v1);
        list.Add(v2);

        foreach (var v in list)
        {
            Console.WriteLine(v.NumberOfWheels);
        }

        Console.ReadKey();
    }
于 2012-05-25T12:39:33.523 に答える