2016-09-01 4 views
-1

Есть ли встроенный/стандартный способ создания отложенного IEnumerable<T>, учитывая Func<IEnumerable<T>>? Мои навыки Google могут быть слабыми ...Создать отложенное перечислимое из Func <IEnumerable <T>>

Предположим, я знаю, что какой-то метод Foo, который возвращает IEnumerable<T>, выполняет немедленно (и, возможно, долго работает). Я хочу, чтобы передать его в метод Bar, который принимает в IEnumerable<T>, но я не хочу Foo быть выполнить его затянувшийся процесс возврата средств до Bar начинает итерацию по элементам:

IEnumerable<string> Foo() 
{ 
    var items = GetItems(); // long running process 
    return items; 
} 

void Bar(IEnumerable<string> foo) 
{ 
    /* something else long-running, or return immediately if some pre-condition fails and we don't even want to iterate over foo */ 
    foreach (var item in foo) 
    { 
     // do something 
    } 
} 

void Run() 
{ 
    IEnumerable<string> foo = GetFooWrapper(Foo) 
    Bar(items); 
} 

IEnumerable<string> GetFooWrapper(Func<IEnumerable<string>> foo) 
{ 
    // ??? 
} 

Какой самый лучший способ внедрения GetFooWrapper? Мой самый простой подход заключался в следующем, но если есть какой-то «лучший» способ сделать это, я хотел бы узнать об этом. Не то чтобы это важно, но R # предлагает упростить его до return foo();.

IEnumerable<string> GetFooWrapper(Func<IEnumerable<string>> foo) 
{ 
    foreach (var item in foo()) 
    { 
     yield return item; 
    } 
} 
+1

Я думаю, если вы _really_ не хотите написать обертку себя, вы могли бы сделать что-то вроде 'Bar (новый Func > [] {() => Foo (элементы)}, х = > x()); Но что случилось с оберткой? У вас есть _специфическая проблема, которую вы пытаетесь решить? Если вы просто хотите, чтобы кто-то просмотрел ваш код, вы должны опубликовать его на codereview.stackexchange.com (конечно же, чтобы соответствовать их требованиям/стандартам публикации). –

+0

У вас есть контроль над перепроектированием 'GetItems'? Если это так, я могу предложить и альтернативное решение –

ответ

0

Похоже, что вы ищете класс Lazy<T>. Он откладывает создание объекта до его первого использования.

Вот пример, который отложил бы выполнение метода Foo до тех пор, пока не получит доступ к объекту Value. Как только Foo будет выполнен один раз, он не будет выполнен повторно, если не будет создан новый Lazy<T>.

var items = new Lazy<IEnumerable<string>>(Foo); 
foreach(var item in items.Value) // delay starts here 
{ 
    // do work 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^