我正在尝试为List类编写safeAdd扩展函数,所以如果它还没有初始化 - 初始化它并添加新值。但是从扩展方法返回后,我刚刚初始化的列表等于null。怎么了?
测试类:
private class Test
{
public Test()
{
Id = Guid.NewGuid();
//items = new List<string>();
}
public Guid Id { get; set; }
public List<string> items { get; set; }
}
扩展类:
public static class Helpers
{
public static void safeAdd<T>(this List<T> list, T item)
{
if (list == null)
list = new List<T>();
list.Add(item);
}
}
主要部分:
Test t = new Test();
t.items.safeAdd("testWord");
//Here t.items == null; WHY?
答案 0 :(得分:7)
您只分配了一个本地方法变量(仅存在于扩展方法中) - 这对调用set
没有任何作用,说实话,没有方便的方法来访问它们get
和set
没有详细,或使用大量反射/ Expression
代码。 IMO只是在课堂上做到了:
private List<string> items;
public List<string> Items { get {
return items ?? (items = new List<string>()); } }
这将在第一次访问时自动初始化并分配列表。
除非我同步,或者(可能更好)使用Interocked.CompareExchange
进行分配,否则它不会是线程安全的。查看联锁
它可以很容易地成为线程安全的,但这很少是实例方法的要求,具有相关的开销
答案 1 :(得分:6)
如果您使用的是.NET 4.0,则可以使用Lazy类自动处理延迟初始化。然后你的代码变成:
private class Test
{
public Test()
{
Id = Guid.NewGuid();
//items = new List<string>();
}
public Guid Id { get; set; }
private Lazy<List<string>> _items = new Lazy<List<string>>();
public List<string> items
{
get { return _items.Value; }
}
}
然后,您可以随时致电Test.items.Add
。它将在首次使用时初始化。
有关详细信息,请参阅Lazy Initialization。