2012-10-24 15 views
6

タイプが実行時に宣言された汎用リスト<を作成します。C#動的総称リスト

私は以下を行うことができますが、動的なので、スピード違反があると思われます。私はエキゾチックなデータベースへのラッパーを書いているので、速度は重要です。

List<dynamic> gdb = new List<dynamic>() 

this postは動的ジェネリック型でありますが、動作させることはできません。具体的には、オブジェクトはListとして表示されないため、addメソッドはありません。

Type ac; 

    switch (trail[dataPos].Type) 
    { 
     case GlobalsSubscriptTypes.Int32: 
      ac = typeof(System.Int32); 

      break; 
     case GlobalsSubscriptTypes.Int64: 
      ac = typeof(System.Int64); 

      break; 

     default: 
      ac = typeof(System.String); 

      break; 
    } 

    var genericListType = typeof(List<>); 
    var specificListType = genericListType.MakeGenericType(ac); 
    var gdb = Activator.CreateInstance(specificListType); 

がどのように私は、次のいずれかのように見えるためにgdbを得るのですか:あなたのケースでは

List<System.Int32> 
List<System.Int64> 
List<System.String> 
+1

これは、その場合に 'List 'を使う方が簡単かもしれません。タイプがコンパイル時に知られていない場合、ジェネリックスが提供するコンパイル時間チェックはあなたに役に立たないでしょう。 – Servy

+0

悪い考えではありませんが、クエリの一部になるので、リストの型を入れたいと思います。 – IamIC

+0

リストについてはどうですか? –

答えて

5

Activator.CreateInstanceを使用したら、結果を適切なタイプにキャストできます。あなたが追加しているタイプは、ジェネリック型と一致しない場合は、上記のArgumentExceptionを投げること

var gdb = (IList)Activator.CreateInstance(specificListType); 
gdb.Add(1); 

注:あなたは、例えばIListを使用することができます。

+0

これは私が探していた答えです。私は間違った場所にキャストしていた。 – IamIC

+0

非ジェネリックインターフェイスを使用する場合は、 'List 'を使うだけでよく、リフレクションを使用してリストを作成する必要はありません。 – Servy

+1

@ intheとlongをboxedとunboxedにする必要がある@Servyは、大きなパフォーマンスヒットです。 – IamIC

1

CreateInstanceは、任意の型のオブジェクトを返すよう、gdbは常に、System.Objectになります。

ここにはいくつかのオプションがありますが、List<T>はこのインターフェイスを実装しており、IList.Addを使用していますので、IList(非汎用)としてキャストできます。

また、あなたはそれdynamic宣言し、動的結合を使用することができます。

dynamic gdb = Activator.CreateInstance(specificListType); 

これは、適切なタイプのList<T>だかのように、あなたのコードを書くようになる、との呼び出しは、実行時にバインドされます動的バインディングを介して

3

Oh gdbは、正しいタイプのです。タイプはランタイムであるため、コンパイラはそれを認識しません。したがって、それはobjectとして静的にタイプされ、Addメソッドを示しません。

  1. 正しい型にキャスト:一般的なスーパーへ

    switch (trail[dataPos].Type) 
    { 
        case GlobalsSubscriptTypes.Int32: 
         ((List<int>) gdb).Add(...); 
         break; 
        ... 
        default: 
         ((List<String>) gdb).Add(...); 
         break; 
    } 
    
  2. 出演:

    ((System.Collections.IList) gdb).Add(...); 
    
  3. 動的呼び出しの使用:

    あなたはそれを修正するためのいくつかのオプションを持っています
    dynamic gdb = Activator.CreateInstance(specificListType); 
    gdb.Add(...); 
    
1

List<dynamic>は、例えば、ボクシング値のタイプを超えて、タイプList<int>より速いペナルティを全く受けません。List<object>と同じタイプがコンパイルされます。あなたがIListにキャストしようとしている場合でも、あなたはまだFYIのボクシングペナルティを持っているつもりです。

コンストラクタを直接呼び出すのが劇的に遅くなる可能性があるので、Activator(リフレクションメソッド)を呼び出していると問題に遭遇する可能性があります。

この問題はありますか?あなたの実際の使用状況に常に依存するため、実際にプロファイルを実行しない限り、あなたはわかりません。

あなたが本当に何をしたいのか私の最高のゲストは、次のとおりです。

IList gdb; 

switch (trail[dataPos].Type) 
{ 
    case GlobalsSubscriptTypes.Int32: 
     gdb = new List<int>(); 
     break; 
    case GlobalsSubscriptTypes.Int64: 
     gdb = new List<long>(); 
     break; 
    default: 
     gdb = new List<string>(); 
     break; 
} 

また、あなたが本当にすべての作業を行うための汎用的なヘルパーメソッドを作るボクシングせずに操作を行う必要がある場合:

switch (trail[dataPos].Type) 
{ 
    case GlobalsSubscriptTypes.Int32: 
     return Helper<int>(trail[dataPos]); 
    case GlobalsSubscriptTypes.Int64: 
     return Helper<long>(trail[dataPos]); 
    default: 
     return Helper<string>(trail[dataPos]); 
} 
+0

あなたの明確な説明をありがとう。ヘルパーのアイデアが好きです(コードについてはあまり考えていませんが)。私は多態性のために、データベースから値を取得するクラスで動的を使用する以外に選択肢はありません。だから私は単にリストと一緒に行くべきだと仮定しています。 – IamIC

+1

@IanC最も単純なコードを作成し、その後速度について心配していても、私は行きます。 – jbtule

関連する問題