在使用对象初始值设定项实例化对象时,如何将项添加到List类型的属性中?

时间:2018-01-31 00:47:41

标签: c#

我希望Books不是null所以我将它作为初始化的只读属性,如下所示。

class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> Books { get; } = new List<string>();
}

由于此约束,我必须首先使用对象初始值设定项实例化对象a,然后通过Books填充其AddRange属性,如下所示。

class Project
{
    void Main()
    {
        Author a = new Author
        {
            Id = 100,
            Name = "Bill Gates"
        };
        a.Books.AddRange(new string[] { "Asp.net", "C++", "C#" });
    }
}

问题

是否有任何技巧可以使用对象初始化程序简化a的实例化(以及填充其Books)?

3 个答案:

答案 0 :(得分:1)

class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> Books { get; } = new List<string>();
    public Author(params string[] books)
    {
        Books.AddRange(books);
    }
}

class Project
{
    void Main()
    {
        Author a = new Author("Asp.net", "C++", "C#")
        {
            Id = 100,
            Name = "Bill Gates"
        };
    }
}

答案 1 :(得分:1)

你可以使用私人套装

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> Books { get; private set; }

   public Author(params string[] books)
    {
        Books = new List<string>(books);
    }
}

或者只使用get(只读选项)

  public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> Books { get; }

    public Author(params string[] books)
    {
        Books = new List<string>(books);
    }
}

私有选项我可以随时在Author中更改列表的实例,但作者之外的任何其他类都只是读它。

只读选项我无法随时更改。我在构造函数中初始化它之后它永远不会改变。

您还可以使用只读集合,初始化后没有正文将添加或删除图书。

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ReadOnlyCollection<string> Books { get; }

    public Author(params string[] books)
    {
        Books = new ReadOnlyCollection<string>(books);
    }
}

答案 2 :(得分:1)

  

由于这个约束,我必须使用对象初始化器实例化第一个 [emphasis mine]对象,然后通过AddRange填充其Books属性

     

但客户端可以将Books设置为null,这是我不想要的。

这些警钟都是使用构造函数来回答的。构造函数的目的是创建有效的对象。构造函数保证有效对象,因为它强制用户提供所需的参数,然后应用其内部状态规则。如果没有构造函数,那么用户和每个用户都有责任强制执行该类的规则 - 并且正确地执行它。

为了确保部分状态,然后允许外部代码随意搞砸它,它应该让读者感到具有讽刺意味和不协调的一个对象被实例化。

修改

回复:“我被迫”发表评论

你专注于修复问题的一半。例如,Name是空的还是空字符串真的可以吗?什么是Author没有名字?在null Name字符串上调用方法会引发异常。要么处理它在构造函数中的所有内容,要么你将在整个地方编写错误捕获,包括客户端代码。客户端代码不应该修复Author的缺点。

但是,如果你必须这样做的话。而这种“懒惰的初始化”并不能消除对合适构造函数的需求。

public List<string> Books { 
   get{ return value; }
   set { if (Books == null) {
            Books = new List<string>(); 
       } else { Books = value; }
   }
}

但那是马车。现有的清单可以消灭。

public Author (string name, List<string> books = null) {
   if(String.isNullOrWhiteSpace(name)) 
      throw new ArgumentException("name is missing");

   // P.S. no public setter properties to undo construction
   Name = name;
   Books = books;  
}

// suggestion: rewrite to use params keyword to add 1 - many at once
public void AddBook( title) {
   if (String.isNullORWhitespace(title)) return;
   Books.Add(title);  // allows duplicates, fyi.

如果有人感到有投票的冲动,请改为投票@HugoJose answer。他早先有效地说明了这一点我只是想解释一个健壮的构造函数的优点。

结束修改