C#List <t>。添加不正确添加</t>

时间:2015-02-27 14:11:13

标签: c#

使用.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; }
}

您可能会注意到get属性WorkOrder.Notes中的编码。我把它放进去,所以财产不会用空值初始化(参考我在SO here上发布的另一个问题的答案)。

利用这些课程:

public void Test()
{
    WorkOrder tempWorkOrder = new WorkOrder();
    Note tempNote = new Note()
    {
        User = "Aaron",
        Time = DateTime.Now,
        NoteText = "Work Order pulled from CSV Excel report."
    };
    tempWorkOrder.Notes.Add(tempNote);
}

我希望Test()中的最后一行将tempNote添加到Note中的tempWorkOrder列表中。但是,此行完成后tempWorkOrder.Notes为空。不会抛出任何错误或异常。

我正在使用VS2013 Express。

我做错了什么?

9 个答案:

答案 0 :(得分:15)

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

get错了。它应该是:

    get
    {
        if (_Notes == null) {
            _Notes = new List<Note>();
        }
        return _Notes;
    }

因为否则您不会保存自己创建的new List<Note>(),并且每次使用get重新创建getnew List<Note>()都会返回_Notes但不会修改get,以便每次_Notes检查null,查看new List<Note>()并返回get

请注意,如果您讨厌这个世界(以及您的其他程序员),您可以将return _Notes ?? (_Notes = new List<Note>()); 压缩为:

{{1}}

(参见Ternary/null coalescing operator and assignment expression on the right-hand side?)我并不厌恶这个世界(以及我的其他程序员)这样做: - )

答案 1 :(得分:1)

您还没有在那里创建列表。您需要向WorkOrder添加构造函数,因为您无法添加到不存在的集合。这样,每当您创建工作订单时,您将在`_Notes'字段中有一个空列表。

它看起来像这样:

WorkOrder(){
    _Notes = new List<Note>();
}

答案 2 :(得分:1)

如果您使用的是C#8,则应该可以使用null-coalescing分配,例如:

get => _Notes ??= new List<Note>();

带有括号:

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

答案 3 :(得分:0)

您永远不会指定_Notes

改为

    private List<Note> _Notes;
    public List<Note> Notes
    {
        get
        {
            if(_Notes == null)
                 _Notes = new List<Note>();
            return _Notes;
        }
        set
        {
            _Notes = value;
        }
    }

答案 4 :(得分:0)

Notes的getter中,您无法保存对新创建的列表的引用。因此,每次访问该getter时,您都会获得一个新的空列表。所以这个:

tempWorkOrder.Notes.Add(tempNote);

...正在将tempNote添加到立即丢弃的List<Note>

答案 5 :(得分:0)

问题是你的get方法:

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

由于您没有将要创建的对象的引用分配给_Notes,因此它保持为null,并且您已分配给未在其他任何位置引用的列表。

这是你可以做的事情:

    get
    {
        if (_Notes == null)
            _Notes = new List<Note>();
        return _Notes;
    }

答案 6 :(得分:0)

您尚未初始化_Notes

因此,当List<Note>为空时,当您获得_Notes时,它不会将对象分配给_Notes。每次访问公共属性时,它都会返回不同的List<Note>,这就是Add()调用似乎不起作用的原因。

你应该使用:

get 
{ 
  if (_Notes == null) 
     _Notes = new List<Note>(); 
  return _Notes; 
}

答案 7 :(得分:0)

public class WorkOrder
{
    public List<Note> Notes {get;set;}

    public WorkOrder()
    {
        Notes = new List<Note>();
    }
}

但是在C#6.0中你应该能够做到以下几点:

public class WorkOrder
{
    public List<Note> Notes {get;set;} = new List<Note>();                
}

答案 8 :(得分:0)

晚了聚会,您可以创建一个小的扩展方法来防止空列表或空列表:

public static bool NotNullAndEmpty<T>(this IEnumerable<T> source)
{
  if (source != null && source.Any())
    return true;
  else
    return false;
}

此外,如果您正在使用数据库,则建议使用IEnumerable并使用IEnumerable进行所有修改。完成后,调用.ToList(),这将导致对数据库的一次调用。