使用
.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。
我做错了什么?
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>());
(请参阅右侧的三元/空合并运算符和赋值表达式?)我对这个世界(和我的程序员同事)的憎恨程度还不足以做到这一点:-)
您还没有在那里创建列表。您需要向
WorkOrder
添加构造函数,因为您无法添加到不存在的集合。这样,每当您创建工单时,“_Notes”字段中都会有一个空列表。
它看起来像这样:
WorkOrder(){
_Notes = new List<Note>();
}
你从不分配
_Notes
改为这样做
private List<Note> _Notes;
public List<Note> Notes
{
get
{
if(_Notes == null)
_Notes = new List<Note>();
return _Notes;
}
set
{
_Notes = value;
}
}
您没有初始化
_Notes
。
因此,当
List<Note>
为空时返回 _Notes
时,它并没有将对象分配给 _Notes
。每次您访问公共财产时,它都会返回不同的 List<Note>
,这就是为什么 Add()
调用似乎不起作用。
你应该使用:
get
{
if (_Notes == null)
_Notes = new List<Note>();
return _Notes;
}
如果您使用 C# 8,应该可以使用空合并赋值,如下所示:
get => _Notes ??= new List<Note>();
带括号:
get
{
return _Notes ??= new List<Note>();
}
在
Notes
的 getter 中,您没有执行任何操作来保存对新创建列表的引用。 因此,每次访问该 getter 时,您都会得到一个新的空列表。 所以这个:
tempWorkOrder.Notes.Add(tempNote);
...正在将
tempNote
添加到立即被丢弃的 List<Note>
。
问题在于你的 get 方法:
get
{
return _Notes ?? new List<Note>();
}
由于您没有将要创建的对象的引用分配给
_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>();
}
}
但是在 C# 6.0 中你应该能够执行以下操作:
public class WorkOrder
{
public List<Note> Notes {get;set;} = new List<Note>();
}
迟到了,您可以创建一个小的扩展方法,可以防止 null 或空列表:
public static bool NotNullAndEmpty<T>(this IEnumerable<T> source)
{
if (source != null && source.Any())
return true;
else
return false;
}
此外,如果您使用数据库,那么建议使用
IEnumerable
并使用 IEnumerable
进行所有修改。完成后,调用 .ToList(
),这将导致对数据库的一次调用。