そのクラスClass name as a string
のジェネリックを作成したいだけのシナリオがあります。List
私は次のことを試しました
Type _type = Type.GetType(className);
List<_type> list = new List<_type>();
しかし、私は得てerror
います。その _type をリスト引数として指定することはできません。誰かが知っているなら、私を助けてください
そのクラスClass name as a string
のジェネリックを作成したいだけのシナリオがあります。List
私は次のことを試しました
Type _type = Type.GetType(className);
List<_type> list = new List<_type>();
しかし、私は得てerror
います。その _type をリスト引数として指定することはできません。誰かが知っているなら、私を助けてください
あなたが得ることができる最も近い:
Type listType = typeof(List<>).MakeGenericType(_type);
IList list = (IList) Activator.CreateInstance(listType);
オブジェクトのタイプは実行中のプログラムによって任意に変更される可能性があるため、リフレクションは実行時に行われます。
一方、型パラメーター(ジェネリック)は、型の安全性をチェックするためにコンパイラーによってのみ使用されます。
したがって、コンパイラはリフレクションの結果について何も知らないため、リフレクションを使用して型パラメータを指定することはできません。
.Net 4 を使用している場合は、使用するとdynamic
役立つ場合があります。この場合、非ジェネリック インターフェイス ( など) を介してアクセスできないインスタンスでメソッドを使用できますIList
。
たとえば、 を使用すると、リストdynamic
のメソッドを呼び出すことがAddRanges
できますが、これは へのキャストでは実行できませんでしたIList
:
Type _type = typeof(int);
Type listType = typeof(List<>).MakeGenericType(_type);
dynamic list = Activator.CreateInstance(listType);
list.Add(1);
list.AddRange(new int[] {0, 1, 2, 3});
ただし、このメソッドは、コンパイル時にエラーをキャッチできないため、非ジェネリック インターフェイスへのキャストほどタイプ セーフではありません。
残念ながら、ジェネリックはコンパイル時に認識される必要があるため、これは不可能です。実行時に通知することで、これを再定義しようとしています。コンパイル時にそれらを知る必要がある理由は、コンパイラーが、渡されたすべての変数が有効であることを検証できるようにするためです。AFAIK、あなたが行きたいことをすることはジェネリックの完全な書き直しを必要とするでしょう。
コンパイル時チェックの背後にある主な理由は、実行時に変更される可能性があり、JITコンパイラが型チェックを行う必要があるため_type
、に追加する際にオーバーヘッドが発生することです。List<T>
@MarkusJarderotが言ったことは、ジェネリックの代わりにインターフェースが使用されるため、取得できる最も近いものです。