C# 设计建议:数组中对象的惰性初始化

C# 设计建议:数组中对象的惰性初始化,c#,.net,singleton,C#,.net,Singleton,我将感谢您对设计问题的帮助: 我有一个单例 我正在考虑给它添加一个memeber:一个实例数组(类x),其中x是一个具有获取一些参数的构造函数的类 我希望数组中的每个单元格都有lazy init 我需要每个对象都是单例的——但是,如果没有模式,整个数组已经是单例的一个成员,是否有任何简化或简单的方法来实现相同的目标 以下情况下,您会向我推荐什么设计: 1) 对阵列对象的访问需要是线程安全的 2) 不需要是类型安全的 提前感谢您的任何想法/建议如果您使用.NET 4,您应该查看一下该类型。 更具体

我将感谢您对设计问题的帮助: 我有一个单例

我正在考虑给它添加一个memeber:一个实例数组(类x),其中x是一个具有获取一些参数的构造函数的类

我希望数组中的每个单元格都有lazy init

我需要每个对象都是单例的——但是,如果没有模式,整个数组已经是单例的一个成员,是否有任何简化或简单的方法来实现相同的目标

以下情况下,您会向我推荐什么设计: 1) 对阵列对象的访问需要是线程安全的 2) 不需要是类型安全的


提前感谢您的任何想法/建议

如果您使用.NET 4,您应该查看一下该类型。

更具体地说,

我有一个类似的要求,因此这里有一个只读列表的示例,它根据请求的索引号惰性地创建实例

在创建时,可以指定元素的数量,并指定如何创建新实例的委托。当通过索引器或枚举器访问元素时,将根据需要调用此委托,例如

var lazyArray = new LazyArray<Tuple<int, int>>(10,
                       i => new Tuple<int, int>(i, 10 - i));
var lazyArray=新的lazyArray(10,
i=>新元组(i,10-i));
该课程的来源如下:

/// <summary>
/// A lazy list for a fixed number of items where items are created on demand
/// </summary>
/// <typeparam name="T">The type of the object the list contains</typeparam>
internal class LazyArray<T> : IList<T> where T : class
{
    private readonly Func<int, T> constructor;
    private readonly IList<T> list;

    public LazyArray(int initialNumberOfItems, Func<int, T> constructor)
    {
        if (constructor == null) throw new ArgumentNullException("constructor");
        this.constructor = constructor;
        list = new T[initialNumberOfItems];
    }

    public IEnumerator<T> GetEnumerator()
    {
        return new Enumerator(this);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Add(T item)
    {
        throw new NotSupportedException();
    }

    public void Clear()
    {
        throw new NotSupportedException();
    }

    public bool Contains(T item)
    {
        return list.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        if (arrayIndex + list.Count > array.Length)
            throw new ArgumentOutOfRangeException("arrayIndex");

        // Remember that we need to access the indexers to create the instance
        // so we can't just copy the list or the array may contain null entries
        for (var i = 0; i < list.Count; i++)
        {
            array[i + arrayIndex] = this[i];
        }
    }

    public bool Remove(T item)
    {
        throw new NotSupportedException();
    }

    public int Count { get { return list.Count; } }
    public bool IsReadOnly { get { return true; } }
    public int IndexOf(T item)
    {
        return list.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
        throw new NotSupportedException();
    }

    public void RemoveAt(int index)
    {
        throw new NotSupportedException();
    }

    public T this[int index]
    {
        get { return list[index] ?? (list[index] = constructor(index)); }
        set { throw new NotSupportedException(); }
    }

    private class Enumerator : IEnumerator<T>
    {
        private readonly LazyArray<T> baseList;
        private int index = -1;

        public Enumerator(LazyArray<T> baseList)
        {
            this.baseList = baseList;
        }

        public bool MoveNext()
        {
            return ++index < baseList.Count;
        }

        public void Reset()
        {
            index = -1;
        }

        public T Current
        {
            get { return baseList[index]; }
        }

        object IEnumerator.Current
        {
            get { return Current; }
        }

        public void Dispose()
        {
        }
    }
}
//
///固定数量项目的延迟列表,其中项目是按需创建的
/// 
///列表包含的对象的类型
内部类LazyArray:IList,其中T:class
{
私有只读Func构造函数;
私有只读IList列表;
公共LazyArray(int initialNumberOfItems,Func构造函数)
{
如果(构造函数==null)抛出新的ArgumentNullException(“构造函数”);
this.constructor=构造函数;
列表=新的T[initialNumberOfItems];
}
公共IEnumerator GetEnumerator()
{
返回新的枚举数(此);
}
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
公共作废新增(T项)
{
抛出新的NotSupportedException();
}
公共空间清除()
{
抛出新的NotSupportedException();
}
公共布尔包含(T项)
{
返回列表。包含(项目);
}
public void CopyTo(T[]数组,int arrayIndex)
{
if(arrayIndex+list.Count>array.Length)
抛出新ArgumentOutOfRangeException(“arrayIndex”);
//记住,我们需要访问索引器来创建实例
//所以我们不能只复制列表,否则数组可能包含空条目
对于(var i=0;i
虽然这不会涵盖所有用例,但我已经成功地使用System.Threading.Interlocked.CompareeExchange()进行了线程安全的惰性对象数组初始化。在调用CompareExchange之前,仍然需要测试空数组元素,并防止数组元素的空读取

if (array[i] == null)
{
    Interlocked.CompareExchange(ref array[i], new Class(), null);
}

对于延迟创建元素的数组,这并没有真正的帮助。@Robert,更具体地说,应该使用
Lazy
的数组(或列表)。这就假设他知道数组中有多少元素,并且这个数字不是很高(否则,在数组初始化过程中创建所有这些惰性对象将受到惩罚)。如果IList或IEnumerable可能是这里的最佳选择,则需要自定义实现。请详细说明几件事……您是否提前知道数组中总共有多少个元素?数组中的项之间是否存在任何关系(您是否可以在不首先为元素3创建值的情况下为元素4创建值)?你是否需要能够检索任意元素的值,或者只在该数组上循环?如果你只在该数组上循环,那么解决方案实际上非常简单…创建一个新的IEnumerable类,而不是数组,并使用“yield”运算符Fredrik,你是对的。我的gmail中的一条规则就是将所有的堆栈放在verflow通知到我的回收站。我如何删除我的旧帖子?