如何通过类扩展懒惰初始化通用List <T>

Jen*_*tor 7 .net c# generics

我正在尝试为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)

Mar*_*ell 7

您只分配了一个本地方法变量(仅存在于扩展方法中) - 这对调用它没有任何作用set,并且说实话,没有方便的方法来访问getset不使用详细信息,或使用大量的反思/ 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可以很容易地使线程安全,但这很少是实例方法的要求,并且  具有相关的开销


Jim*_*hel 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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以随时致电Test.items.Add.它将在首次使用时初始化.

有关更多信息,请参阅延迟初始化.