C#列表<;T>;。添加未正确添加

C#列表<;T>;。添加未正确添加,c#,C#,使用.Add将类的实例添加到泛型列表中不起作用 为了说明这个问题,这里有两个简单的示例类: public class WorkOrder { private List<Note> _Notes; public List<Note> Notes { get { return _Notes ?? new List<Note>(); } set

使用
.Add
将类的实例添加到泛型列表中不起作用

为了说明这个问题,这里有两个简单的示例类:

public class WorkOrder
{
    private List<Note> _Notes;
    public List<Note> Notes
    {
        get
        {
            return _Notes ?? new List<Note>();
        }
        set
        {
            _Notes = value;
        }
    }
}

public class Note
{
    public string NoteText { get; set; }
    public System.DateTime Time { get; set; }
    public string User { get; set; }
}
我希望
Test()
中的最后一行将
tempNote
添加到
tempWorkOrder
中的
Note
列表中。但是,此行完成后,
tempWorkOrder.Notes
为空。不会引发任何错误或异常

我正在使用VS2013 Express


我做错了什么?

您还没有在那里创建列表。您需要将构造函数添加到
工作顺序中,因为您无法添加到不存在的集合中。这样,无论何时创建工单,“备注”字段中都会有一个空列表

它看起来像这样:

WorkOrder(){
    _Notes = new List<Note>();
}
WorkOrder(){
_注释=新列表();
}
否则,您不会保存创建的
new List()
,每次使用
get
时都会重新创建它(
get
返回
new List()
,但不会修改
\u Notes
,因此每次
get
都会检查
\u Notes
,请查看它的
null
并返回
新列表()

请注意,如果您讨厌这个世界(以及您的程序员同伴),您可以压缩
get

return _Notes ?? (_Notes = new List<Note>());
return\u Notes??(_Notes=新列表());

(请参阅)我对这个世界(以及我的程序员同事)的憎恨还不够深,无法做到这一点:-)

你从来没有分配过
\u Notes

改为这样做

    private List<Note> _Notes;
    public List<Note> Notes
    {
        get
        {
            if(_Notes == null)
                 _Notes = new List<Note>();
            return _Notes;
        }
        set
        {
            _Notes = value;
        }
    }
private List\u Notes;
公开名单注释
{
得到
{
如果(_Notes==null)
_注释=新列表();
还票;;
}
设置
{
_注释=价值;
}
}

注释的getter中,您没有保存对新创建列表的引用。因此,每次访问该getter时,都会得到一个新的空列表。因此:

tempWorkOrder.Notes.Add(tempNote);

…正在将
tempNote
添加到立即丢弃的
列表中。

问题在于获取方法:

    get
    {
        return _Notes ?? new List<Note>();
    }

您没有初始化注释

因此,当
\u Notes
为空时,返回
列表时,它不会将对象分配给
\u Notes
。每次访问公共属性时,它都会返回不同的
列表
,这就是为什么
Add()
调用似乎不起作用的原因

你应该使用:

get 
{ 
  if (_Notes == null) 
     _Notes = new List<Note>(); 
  return _Notes; 
}
get
{ 
如果(_Notes==null)
_注释=新列表();
还票;;
}
公共类工作订单
{
公共列表注释{get;set;}
公共工单()
{
注释=新列表();
}
}
但在C#6.0中,您应该能够做到以下几点:

public class WorkOrder
{
    public List<Note> Notes {get;set;} = new List<Note>();                
}
公共类工作订单
{
公共列表注释{get;set;}=new List();
}

迟到时,您可以创建一个小的扩展方法来防止空列表或空列表:

public static bool NotNullAndEmpty<T>(this IEnumerable<T> source)
{
  if (source != null && source.Any())
    return true;
  else
    return false;
}
公共静态bool NotNullAndEmpty(此IEnumerable源代码)
{
if(source!=null&&source.Any())
返回true;
其他的
返回false;
}

另外,如果您使用的是数据库,建议使用
IEnumerable
并使用
IEnumerable
进行所有修改。完成后,调用
.ToList(
),这将导致对数据库的单个调用。

如果您使用的是C#8,则应该可以使用空合并赋值,如下所示:

get=>\u Notes???=newlist()

括号内:

get
{
返回_Notes???=新列表();

}

在EF中(这是OP在另一个问题中所做的)这是初始化ICollections的正常方法。只想指出:这个问题是针对一个不与EF绑定的类的-虽然是的,它可以很容易地在代码优先的情况下应用。我不会懒洋洋地创建列表的实例-你可能会导致一些意外的行为。return\u Notes??新列表();执行以下操作,如果_Notes不为null,则返回它;如果为null,则创建并返回一个新列表,但从未分配给_Notes。就是这样。看起来到目前为止所有的答案都是正确的,但这一个答案最完整。谢谢大家!我没有收到
返回注释的“仇恨”??(_Notes=新列表())。我认为它非常清晰,事实上我更喜欢它,而不是一行
if
。链接的线程显示出一些误用的可能性,但您几乎可以误用所有内容。@Corak单行if是因为我直接在的编辑器中编写,因此不会自动缩进:-)我总是使用
if{}
。另一个表达式中
=
的“仇恨”可能与编写代码的“一行一效”方式和/或C/C++@xanatos中
=
赋值与
=
相等运算符引起的大量错误有关-谢谢,我明白了。好吧,有了“一行,一个效果”,Linq方法链接就走不远了@Corak没有,因为Linq方法没有副作用(链的每个成员都会产生新的东西),所以它们是可以的。
    get
    {
        if (_Notes == null)
            _Notes = new List<Note>();
        return _Notes;
    }
get 
{ 
  if (_Notes == null) 
     _Notes = new List<Note>(); 
  return _Notes; 
}
public class WorkOrder
{
    public List<Note> Notes {get;set;}

    public WorkOrder()
    {
        Notes = new List<Note>();
    }
}
public class WorkOrder
{
    public List<Note> Notes {get;set;} = new List<Note>();                
}
public static bool NotNullAndEmpty<T>(this IEnumerable<T> source)
{
  if (source != null && source.Any())
    return true;
  else
    return false;
}