将 IEnumerable<T> 初始化为新的 List<T>

问题描述

我有一堂这样的课:

public class ItemList
{
    [JsonProperty("items")]
    public IEnumerable<Item> Items { get; set; }
}

我想初始化空列表,如下所示:

var newItemList = new ItemList
{
    Items = new List<Item>()
};

但是 Items 仍然是 IEnumerable,我不能使用 Add 或其他列表方法

解决方法

为什么不将其声明为列表

public class ItemList
{
    [JsonProperty("items")]
    public List<Item> Items { get; set; }
}

List 是 IEnumerable 的扩展,因此将其声明为列表并具有所有方法是有意义的。

由于您已经声明为 public IEnumerable<Item> Items { get; set; },因此不会更改。

你可以这样做:

Items = new List<Item>();

甚至

ItemList itemlist = new itemlist();
itemlist.Items = new List<Item>();
((List<Item>)itemlist.Items).Add(new Item());

但是 ((List<Item>)itemlist.Items).Add(new Item()); 并不安全。当您初始化为列表时它会起作用,但如果您尝试从其他 IEnumerable 类型进行转换,它将导致运行时异常。

,

您可以使用以下两个选项之一。

  1. 你可以像下面这样使用 List Initializer

     var itemList = new ItemList() {
         Items = new List<Item>() {
             new Item() { Name = "One" },new Item() { Name = "Two" }
         }
     };
    
  2. 您可以完全初始化列表,然后将其分配给 Items

  3. 更好的方法是使用 Builder 模式,它有助于构建 https://code-maze.com/fluent-builder-recursive-generics/

    中所述的 ItemList
,

拥有 IEnumerable 可以让您实现 SOLID 原则之一,即您必须依赖抽象而不是具体的类。这意味着您可以在该属性(列表、HashSet 等...)中存储 IEnumerable 的任何实现。

如果要使用List类实现的Add方法,必须把IEnumerable转成List

var myList = newItemList.ToList<T>();
myList.Add(new T());

其中 T 是您的具体类。

,

当然可以,只需投射即可:

(Items as List<Item>).Add(someItem);

可能会一直很无聊:

public class ItemList
{
    private List<Item> _items - new List<Item>;
    [JsonProperty("items")]
    public IEnumerable<Item> Items { get => _items; private set => _items = value as List<string>; }
}

然后在类中可以使用 _items

我建议您将该 setter 设为私有,并将项目设置为内部类的列表;集合上需要强制转换,但如果其他人传入一个不是 List 的 IEnumerable,它将导致项目集合设置为 null。

如果你决定外部类会看到一个 IEnumerable 但你要把它作为一个列表,那么你不应该给任何使用你的类的人机会将它更改为不是一个列表..

如果您只打算设置一次列表(永远不要为新实例更改它),例如在构造函数中,然后您可以将属性设为只读