如何创建一个包含动态对象类型的列表

41

我该如何创建一个新的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个回答

81

只需将dynamic作为参数即可:

var list = new List<dynamic>();

@Krik 谢谢。这是我做的。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 中的所有对象都被最后一个分配的对象的值所替换。 - BumbleBee
4
@BumbleBee,这是因为您正在覆盖对象的值。您实例化了一个 DyObj 实例,然后继续两次为同一实例分配值。应该将 dynamic DyObj = new ExpandoObject(); 这行代码放在 if 块内部,并且您应该最终得到两个该行代码的副本,因为您想要添加两个不同的实例。 - Kirk Woll

9

看起来您可能有些困惑 .Add 方法的工作方式。我将直接参考您的代码进行解释。

在 C# 中,对象列表的 .Add 方法不会复制新添加的对象到列表中,它仅仅是将对象的引用(地址)复制到列表中。因此,列表中每个值指向同一个值的原因是因为只创建了一个新的 DyObj。所以您的列表实际上看起来像这样。

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 块内部放置新的 DyObj 可以在这种特定情况下实现此目标。
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操作,它们确实存在于你的List中),那么C#不会释放与该指针相关联的内存。因此,在该代码块中创建的对象将持续存在,你的List包含指向有效对象的指针,你的代码可以正常工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接