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

问题描述 投票:0回答:9

使用

.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。

我做错了什么?

c#
9个回答
19
投票
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
时都会重新创建它(
get
返回
new List<Note>()
但不会修改
_Notes
,因此每个
get
检查
_Notes
,看到了
null
并返回
new List<Note>()
)

您可以将

get
压缩为:

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

(请参阅右侧的三元/空合并运算符和赋值表达式?)我对这个世界(和我的程序员同事)的憎恨程度还不足以做到这一点:-)


2
投票

您还没有在那里创建列表。您需要向

WorkOrder
添加构造函数,因为您无法添加到不存在的集合。这样,每当您创建工单时,“_Notes”字段中都会有一个空列表。

它看起来像这样:

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

1
投票

你从不分配

_Notes

改为这样做

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

1
投票

您没有初始化

_Notes

因此,当

List<Note>
为空时返回
_Notes
时,它并没有将对象分配给
_Notes
。每次您访问公共财产时,它都会返回不同的
List<Note>
,这就是为什么
Add()
调用似乎不起作用。

你应该使用:

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

1
投票

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

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

带括号:

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


0
投票

Notes
的 getter 中,您没有执行任何操作来保存对新创建列表的引用。 因此,每次访问该 getter 时,您都会得到一个新的空列表。 所以这个:

tempWorkOrder.Notes.Add(tempNote);

...正在将

tempNote
添加到立即被丢弃的
List<Note>


0
投票

问题在于你的 get 方法:

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

由于您没有将要创建的对象的引用分配给

_Notes
,因此它一直为空,并且您分配给了一个在其他任何地方都没有引用的列表。

您可以这样做:

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

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>();                
}

0
投票

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

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

此外,如果您使用数据库,那么建议使用

IEnumerable
并使用
IEnumerable
进行所有修改。完成后,调用
.ToList(
),这将导致对数据库的一次调用。

© www.soinside.com 2019 - 2024. All rights reserved.