简体   繁体   中英

Enumerable and deferred execution of a method

I have a method: int[] GetNumbers (); which immediately returns array of numbers. However I can call this method only when class is initialized. I cannot initialize this class manually, it is initialized somewhere else by someone else.
I want to create IEnumerable which will call GetNumbers() when I will start iterating over that enumerable.

example:

    IEnumerable<int> numbers = new SomeKindOfWrapper (() => GetNumbers());

Now GetNumbers() will be called only when I try to access numbers .

How to achieve this? Is there something in NET framework that supports it?

I can pass delegate to my class which will call GetNumbers(), but I prefer IEnumerable.

Simply create an iterator block that invokes the delegate and then yields the values in the sequence:

public static IEnumerable<T> SomeKindOfWrapper<T>(
    Func<IEnumerable<T>> generator)
{
    foreach(var item in generator())
        yield return item;
}

If you want to ensure that the delegate is never invoked more than once you can use Lazy instead:

public static IEnumerable<T> SomeKindOfWrapper<T>(
    Lazy<IEnumerable<T>> sequence)
{
    foreach(var item in sequence.Value)
        yield return item;
}

One kind of wrapper that you could use is Lazy<T> :

Lazy<IEnumerable<int>> numbers = new Lazy<IEnumerable<int>>(() => GetNumbers());

You can use numbers.Value , or add a wrapper property for it:

IEnumerable<int> Numbers {
    get {
        return numbers.Value;
    }
}

The call of GetNumbers() is deferred until the first call of numbers.Value . After that the result is stored inside Lazy<T> , and returned to you on subsequent calls of numbers.Value .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM