web-dev-qa-db-ja.com

動的オブジェクトタイプでリストを作成する方法

[〜#〜] t [〜#〜]dynamic Typeオブジェクトである新しいList<T>を作成するにはどうすればよいですか。

私が持っています

dynamic DyObj = new ExpandoObject();

if (condition1)
{
  DyObj.Required = true;
  DyObj.Message = "This is the first property being accessed through dynamic object";
}
if (condition2)
{
    DyObj.Required = false;
    DyObj.Message = "This is the second property....";
}
// and so on...

List<Dyobj>を作成し、条件に基づいてすべてのメッセージをDyobjに割り当てます。

コメントからのフォローアップデータ:

var DyObjectsList = new List<dynamic>; 
dynamic DyObj = new ExpandoObject(); 
if (condition1) { 
    DyObj.Required = true; 
    DyObj.Message = "Message 1"; 
    DyObjectsList.Add(DyObj); 
} 
if (condition2) { 
    DyObj.Required = false; 
    DyObj.Message = "Message 2"; 
    DyObjectsList.Add(DyObj); 
} 

興味深いことに、DyObjectsListのすべてのオブジェクトは、最後に割り当てられたオブジェクトの値に置き換えられます。

28
BumbleBee

引数としてdynamicを使用するだけです:

var list = new List<dynamic>();
56
Kirk Woll

.Addメソッドの動作について少し混乱しているように見えます。説明でコードを直接参照します。

基本的にC#では、オブジェクトのリストの.Addメソッドは、新しく追加されたオブジェクトをリストにコピーせず、オブジェクトへの参照(アドレス)をリストにコピーするだけです。したがって、リスト内のすべての値が同じ値を指しているのは、新しいDyObjを1つだけ作成したためです。したがって、リストは基本的に次のようになります。

DyObjectsList[0] = &DyObj; // pointing to DyObj
DyObjectsList[1] = &DyObj; // pointing to the same DyObj
DyObjectsList[2] = &DyObj; // pointing to the same DyObj

...

コードを修正する最も簡単な方法は、.Addごとに新しいDyObjを作成することです。 .Addを使用して新しいブロックをブロックの内側に配置すると、この特定のインスタンスでこの目標を達成できます。

var DyObjectsList = new List<dynamic>; 
if (condition1) { 
    dynamic DyObj = new ExpandoObject(); 
    DyObj.Required = true; 
    DyObj.Message = "Message 1"; 
    DyObjectsList .Add(DyObj); 
} 
if (condition2) { 
    dynamic DyObj = new ExpandoObject(); 
    DyObj.Required = false; 
    DyObj.Message = "Message 2"; 
    DyObjectsList .Add(DyObj); 
} 

結果のリストは基本的に次のようになります

DyObjectsList[0] = &DyObj0; // pointing to a DyObj
DyObjectsList[1] = &DyObj1; // pointing to a different DyObj
DyObjectsList[2] = &DyObj2; // pointing to another DyObj

他の一部の言語では、このアプローチは機能しません。ブロックを離れると、ブロックのスコープで宣言されたオブジェクトがスコープから外れて破棄される可能性があるためです。したがって、ごみを指すポインターのコレクションが残されます。

ただし、C#では、ブロックを離れるときに新しいDyObjsへの参照が存在する場合(および.Add操作のためにリストに存在する場合)、C#はそのポインターに関連付けられているメモリを解放しません。したがって、そのブロックで作成したオブジェクトは保持され、リストには有効なオブジェクトへのポインターが含まれ、コードが機能します。

5
Daniel Byrne