2016-07-25 4 views
3

Если я запрашиваю EF, используя что-то вроде этого ...Force IEnumerable <T> оценить без вызова .ToArray() или .ToList()

IEnumerable<FooBar> fooBars = db.FooBars.Where(o => o.SomeValue == something); 

IIRC, Это создает ленивую-оценивали, Iterable государственную машину в фон, который еще не содержит никаких результатов; скорее, он содержит выражение «как» для получения результатов, когда это необходимо.

Если я хочу, чтобы заставить коллекцию содержать результаты, которые я должен позвонить .ToArray() или .ToList()

Есть ли способ, чтобы заставить IEnumerable<T> коллекцию, чтобы содержать результаты без вызова .ToArray() или .ToList();?

Обоснование

Я не знаю, если CLR способен сделать это, но, по сути, я хочу, чтобы принудительно создать оцененную коллекцию, которая реализует интерфейс IEnumerable<T>, но реализуется под капотом в CLR , таким образом нЕList<T> или Array<T>

Предположительно, это не представляется возможным, так как я не знаю ни возможности CLR для создания в памяти, оцениваемые коллекции, которые реализуют IEnumerable<T>

Предложение

Скажем, например, я мог бы написать что-то вроде этого:

var x = IEnumerable<FooBar> fooBars = db.FooBars 
     .Where(o => o.SomeValue == something) 
     .Evaluate(); // Does NOT return a "concrete" impl such as List<T> or Array<T> 

Console.WriteLine(x.GetType().Name); 
// eg. <EvaluatedEnumerable>e__123 
+6

Что не так с вызовом '.ToList()'? – user3185569

+4

Да. Используя цикл 'Foreach'. –

+1

Результаты должны храниться в * something *, поэтому вам нужен список, массив или какой-либо другой тип коллекции. –

ответ

5

Есть ли способ, чтобы заставить IEnumerable<T> коллекцию, чтобы содержать результаты без вызова .ToArray() или .ToList();?

Да, но это, возможно, не то, что вы хотите:

IEnumerable<T> source = …; 
IEnumerable<T> cached = new List<T>(source); 

Дело в том, IEnumerable<T> не конкретный тип. Это интерфейс (контракт), представляющий последовательность элементов. Может существовать какой-либо конкретный тип «скрываясь за» этим интерфейсом; некоторые могут представлять только запрос, другие фактически хранят запрошенные элементы в памяти.

Если вы хотите принудительно оценить последовательность, чтобы результат был фактически сохранен в физической памяти, вам необходимо убедиться, что конкретный тип за IEnumerable<T> является коллекцией памяти, в которой хранятся результаты оценки. Вышеприведенный пример кода делает именно это.

+3

Стоит отметить, что это фактическая реализация метода '.ToList()' за пределами вытяжек. – user3185569

4

Вы можете использовать foreach цикл:

foreach (var item in fooBars) { } 

Заметьте, что это оценивает все элементы в fooBars , но сразу же отбрасывает результат. В следующий раз, когда вы запустите тот же цикл foreach или .ToArray(), .ToList(), перечислимое будет оцениваться еще раз.

+1

Тогда * коллекция содержит результаты *, как указано OP: нет, она перечисляется каждый раз, когда вы выполняете цикл foreach. 'IEnumerable' содержит информацию о том, как получить данные, а не сами данные. Если тип времени выполнения не является списком и Тип времени компиляции - 'IEnumerable' (например,' IEnumerable fooBars = db.FooBars.Where (o => o.SomeValue == something) .ToList(); ' – user3185569

+0

Зачем вам предлагать это сделать? point: для запуска запроса ни для чего? – Sinatr

+1

@Sinatr: Теоретически запрос может иметь побочные эффекты, поэтому кажущийся пустой цикл может действительно что-то сделать. Запрос, имеющий побочные эффекты, не совсем то, что ИМО, но это возможность все же. – stakx