如何通过类扩展</t>延迟初始化通用List <t>

时间:2011-12-26 19:45:51

标签: c# .net 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; }
}

扩展类:

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?

2 个答案:

答案 0 :(得分:7)

您只分配了一个本地方法变量(仅存在于扩展方法中) - 这对调用set没有任何作用,说实话,没有方便的方法来访问它们getset没有详细,或使用大量反射/ 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