Как создать список с динамическим типом объекта - PullRequest
28 голосов
/ 06 июля 2011

Как мне создать новый List<T>, где 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 заменены значениями последнего назначенного объекта.

Ответы [ 2 ]

55 голосов
/ 06 июля 2011

Просто используйте dynamic в качестве аргумента:

var list = new List<dynamic>();
5 голосов
/ 06 декабря 2012

Похоже, вы можете быть немного озадачены тем, как работает метод .Add.В своем объяснении я буду ссылаться непосредственно на ваш код.

В основном в C # метод .Add объекта List не копирует новые добавленные объекты в список, он просто копирует ссылку на объект (этоадрес) в список.Таким образом, причина того, что каждое значение в списке указывает на одно и то же значение, заключается в том, что вы создали только 1 новый DyObj.Таким образом, ваш список по сути выглядит следующим образом.

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

...

Самый простой способ исправить ваш код - это создать новый DyObj для каждого .Add.Помещение нового внутри блока с помощью .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 (и они существуют в вашем Списке из-за.Операция добавления), тогда C # не освобождает память, связанную с этим указателем.Поэтому объекты, которые вы создали в этом блоке, сохраняются, и ваш список содержит указатели на допустимые объекты, и ваш код работает.

...