我正在尝试为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; }
}
Run Code Online (Sandbox Code Playgroud)
扩展类:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
主要部分:
Test t = new Test();
t.items.safeAdd("testWord");
//Here t.items == null; WHY?
Run Code Online (Sandbox Code Playgroud)
您只分配了一个本地方法变量(仅存在于扩展方法中) - 这对调用它没有任何作用set,并且说实话,没有方便的方法来访问get和set不使用详细信息,或使用大量的反思/ Expression代码.IMO就是在课堂上做的:
private List<string> items;
public List<string> Items { get {
return items ?? (items = new List<string>()); } }
Run Code Online (Sandbox Code Playgroud)
这将在第一次访问时自动初始化并分配列表.
它不是线程安全的,除非我同步,或(可能更喜欢)用于Interocked.CompareExchange 赋值.View Interlocked可以很容易地使线程安全,但这很少是实例方法的要求,并且 具有相关的开销
如果您使用的是.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; }
}
}
Run Code Online (Sandbox Code Playgroud)
然后您可以随时致电Test.items.Add.它将在首次使用时初始化.
有关更多信息,请参阅延迟初始化.