Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当使用对象初始值设定项实例化对象时,如何向列表类型的属性添加项?_C# - Fatal编程技术网

C# 当使用对象初始值设定项实例化对象时,如何向列表类型的属性添加项?

C# 当使用对象初始值设定项实例化对象时,如何向列表类型的属性添加项?,c#,C#,我希望Books不为null,因此我将其设置为初始化的只读属性,如下所示 class Author { public int Id { get; set; } public string Name { get; set; } public List<string> Books { get; } = new List<string>(); } class Project { void Main() { Author

我希望
Books
不为
null
,因此我将其设置为初始化的只读属性,如下所示

class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> Books { get; } = new List<string>();
}
class Project
{
    void Main()
    {
        Author a = new Author
        {
            Id = 100,
            Name = "Bill Gates"
        };
        a.Books.AddRange(new string[] { "Asp.net", "C++", "C#" });
    }
}
问题: 使用对象初始值设定项可以简化
a
的实例化(以及填充
书籍
)吗?

类作者
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"
        };
    }
}
{ 公共int Id{get;set;} 公共字符串名称{get;set;} 公共列表书籍{get;}=new List(); 公共作者(参数字符串[]图书) { 图书。添加范围(图书); } } 班级项目 { void Main() { 作者a=新作者(“Asp.net”、“C++”、“C#”) { Id=100, Name=“比尔·盖茨” }; } }
类作者
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共列表书籍{get;}=new List();
公共作者(参数字符串[]图书)
{
图书。添加范围(图书);
}
}
班级项目
{
void Main()
{
作者a=新作者(“Asp.net”、“C++”、“C#”)
{
Id=100,
Name=“比尔·盖茨”
};
}
}

您可以使用专用设置

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);
    }
}
公共类作者
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共列表图书{get;private set;}
公共作者(参数字符串[]图书)
{
图书=新列表(图书);
}
}
或者使用just get(只读选项)

公共类作者
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共列表图书{get;}
公共作者(参数字符串[]图书)
{
图书=新列表(图书);
}
}
private选项我可以在Author内部随时更改列表的实例,但是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);
    }
}
公共类作者
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共只读收集书籍{get;}
公共作者(参数字符串[]图书)
{
图书=新的只读集合(图书);
}
}

您可以使用专用设置

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);
    }
}
公共类作者
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共列表图书{get;private set;}
公共作者(参数字符串[]图书)
{
图书=新列表(图书);
}
}
或者使用just get(只读选项)

公共类作者
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共列表图书{get;}
公共作者(参数字符串[]图书)
{
图书=新列表(图书);
}
}
private选项我可以在Author内部随时更改列表的实例,但是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);
    }
}
公共类作者
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共只读收集书籍{get;}
公共作者(参数字符串[]图书)
{
图书=新的只读集合(图书);
}
}
由于这个限制,我必须先用对象初始值设定项实例化对象a[emphasis mine],然后通过AddRange填充其Books属性

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

这些警报都是通过使用构造函数来响应的。构造函数的目的是创建有效的对象。构造函数保证一个有效的对象,因为它强制用户提供所需的参数,然后应用其内部状态规则。没有构造函数,用户和每个用户都有责任强制执行该类的规则,并正确执行

读者会觉得,实例化一个对象是为了确保部分状态,然后允许外部代码随意地把它搞砸,这是讽刺和不协调的

编辑

回复:“我被迫”的评论

你只专注于解决一半的问题。例如,
Name
为null或空字符串真的可以吗?没有名字的
作者是什么?对空名称字符串调用方法会引发异常。要么在构造函数中处理它的所有内容,要么编写错误捕获程序,包括客户端代码。客户端代码不应修复作者的缺点

但是,如果你必须的话,你可以这样做。这种“延迟初始化”并不能消除对一个好的构造函数的需求

public List<string> Books { 
   get{ return value; }
   set { if (Books == null) {
            Books = new List<string>(); 
       } else { Books = value; }
   }
}
公共列表图书{
获取{返回值;}
设置{if(Books==null){
书籍=新列表();
}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.
public Author(字符串名,列表簿=null){
if(String.isNullOrWhiteSpace(name))
抛出新ArgumentException(“缺少名称”);
//P.S.无可撤消构造的公共setter属性
名称=名称;
书=书;
}
//建议:重写以使用params关键字一次添加1-多个
公共无效地址簿(标题){
if(String.isNullORWhitespace(title))返回;
Books.Add(title);//允许复制,仅供参考。
如果有人想投票,那就投票吧。他在前面有效地说明了这一点。我只是想解释健壮构造函数的优点

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

由于这个限制,我必须先用对象初始值设定项实例化对象a[emphasis mine],然后通过AddRange填充其Books属性

但是客户可以设置帐簿