列出动态生成的元素

时间:2016-08-22 18:02:11

标签: .net list dynamic

我有一个函数返回一个只读的值列表。在某些情况下,这个值列表可能会变得非常大,可以通过算法来描述。我希望列表按请求动态生成这些值,而不是生成包含所有这些值的列表。如果我需要自己实现更多算法,是否有任何通用或模板或其他任何可以让我开始的东西?

我意识到这个想法本身是相当通用的,但我把它作为一个起点标记为我的具体案例。

2 个答案:

答案 0 :(得分:2)

由于List<T>表示内存中的集合,因此无法在不将其存储在内存中的情况下动态生成其成员。

但是,您可以使用IEnumerable<T>:在循环中使用yield return语句动态生成序列的项目:

public IEnumerable<int> RandomlyIncreasing() {
    var rnd = new Random();
    var current = rnd.Next(0, 50);
    for (int i = 0 ; i != 1000000 ; i++) {
        yield return current;
        current += rnd.Next(0, 10);
    }
}

Demo.

答案 1 :(得分:0)

正如dasblinkenlight所述,List必须包含元素。根据其实现的接口IListICollection的定义。如果您想返回代表值列表的内容,则IEnumerable是您唯一的选择。检查此实现。

public class FunctionBasedList<T> : IEnumerable<T>
{
    public class Enumerator<T> : IEnumerator<T>
    {
        private int index;
        private T current;

        private FunctionBasedList<T> list;

        internal Enumerator(FunctionBasedList<T> list)
        {
            this.list = list;
        }

        public T Current {
            get
            {
                return current;
            }
        }

        Object IEnumerator.Current
        {
            get
            {
                if (index == 0 || index == this.list.Count + 1)
                {
                    throw new InvalidOperationException();
                }

                return current;
            }
        }

        public bool MoveNext()
        {
            if (list.Count > index)
            {
                current = this.list[index];
                index++;
                return true;
            }

            return false;
        }

        public void Reset()
        {
            index = 0;
            current = default(T);
        }

        public void Dispose()
        {

        }
    }

    public int Count
    {
        private set;
        get;
    }

    public Func<int, T> Function
    {
        private set;
        get;
    }

    public T this[int index]
    {
        get
        {
            if (index < 0 || index >= this.Count)
            {
                throw new IndexOutOfRangeException();
            }

            return this.Function(index);
        }
    }

    public FunctionBasedList(int count, Func<int, T> function)
    {
        this.Count = count;
        this.Function = function;
    }

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

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

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

class Program
{
    static void Main(string[] args)
    {
        FunctionBasedList<int> readOnlyList = new FunctionBasedList<int>(
            10,
            (index) =>
            {
                //Arbitrary function to generate a specific value for a specific index
                return index * 100;
            });

        foreach (int r in readOnlyList)
        {
            Console.WriteLine(r);
        }

        //Loop through a subset of the list
        for (int i = 5; i < 8; i++)
        {
            Console.WriteLine(readOnlyList[i]);
        }

        //Will throw an IndexOutOfRangeException
        Console.WriteLine(readOnlyList[10]);
    }
}

您可以返回IEnumerator,并在不同情况下使用List<T>FunctionBasedList<T>