Почему использование.AsEnumerable () вместо того, чтобы бросить к IEnumerable <T>?

Один из дополнительных методов на IEnumerable<T> .AsEnumerable(). Этот метод преобразовывает счетный объект, из которого к нему обратились в экземпляр IEnumerable<T>. Однако, так как объект должен реализовать IEnumerable<T> для применения к этому дополнительному методу, преобразовав в IEnumerable<T> простой вопрос кастинга к IEnumerable<T>. Мой вопрос состоит в том, почему этот метод существует вообще?

Пример:

List<string> strings = new List<string>() { "test", "test2", "test3" };
IEnumerable<string> stringsEnum1 = strings.AsEnumerable();
IEnumerable<string> stringsEnum2 = (IEnumerable<string>)strings;

В примере выше, stringsEnum1 и stringsEnum2 эквивалентны. Какой смысл дополнительного метода?

Править: Как заключение, почему там .AsQueryable() метод при кастинге к IQueryable<T> эквивалентно?

63
задан Erik Forbes 6 January 2010 в 15:36
поделиться

4 ответа

[

] Читабельность здесь основная проблема. Считайте, что[

] [
Table.AsEnumerable().Where(somePredicate)
] [

]намного более читабельная, чем[

] [
((IEnumerable<TableObject>)Table).Where(somePredicate).
] [

]Или представьте себе желание выполнить часть запроса на SQL сервере, а остальную часть - в памяти:[

] [
Table.Where(somePredicate)
     .Select(someProjection)
     .AsEnumerable()
     .SomethingElse()
] [

]против[

] [
((IEnumerable<SomeProjectionType>)Table.Where(somePredicate)
                                       .Select(someProjection))
                                       .SomethingElse()
] [

]Теперь, а зачем вообще полезен такой метод, вспомните пример []Table[] в LINQ to SQL []DataContext[]. Так как []Table[] является []IQueryable[], то он реализует []IEnumerable[]. Когда вы вызываете метод [] Where[] на такой []Table[] и перечисляете по результатам, выполняется код, который в конечном итоге приводит к выполнению SQL-запроса на SQL-сервере. Что делает []AsEnumerable[], это говорит, нет, я не хочу использовать LINQ to SQL провайдера для выполнения []Where[], я хочу использовать LINQ to Objects реализацию []Where[]. [

] [

]Таким образом, перечисление по[

] [
Table.Where(somePredicate)
] [

] вызывает запрос на SQL-сервере, а перечисление по[

] [
Table.AsEnumerable().Where(somePredicate)
] [

] приносит в память таблицу, представленную []Table[], и выполняет функцию []Where[] в памяти (а не на SQL-сервере! )[

] [

]В этом и заключается смысл []AsEnumerable[]: позволить скрыть конкретную реализацию методов []IEnumerable[] и вместо этого использовать стандартную реализацию.[

].
84
ответ дан 24 November 2019 в 16:21
поделиться

Я придумал причину, помимо удобочитаемости, хотя и связанную с реализацией запроса: использование Linq to Objects на анонимных типах, возвращаемых через другой Linq провайдер. Вы не можете приводить к анонимному типу (или коллекции анонимных типов), но вы можете использовать .AsEnumerable(), чтобы выполнить приведение за вас.

Пример:

// Get an IQueryable of anonymous types.
var query = from p in db.PeopleTable /* Assume Linq to SQL */
            select new { Name = p.Name, Age = p.Age };

// Execute the query and pull the results into an IEnumerable of anonymous types
var enum = query.AsEnumerable();

// Use Linq to Objects methods to further refine.
var refined = from p in enum
              select new
              {
                  Name = GetPrettyName(p.Name),
                  DOB = CalculateDOB(p.Age, DateTime.Now)
              };

Очевидно, что причина здесь в том, что мы хотим использовать что-то вроде Linq to SQL, чтобы вытащить некоторые записи в анонимный тип, а затем выполнить некоторую пользовательскую логику (что было бы невозможно с помощью Linq to SQL), используя Linq to Objects на стороне клиента.

Вставка в IEnumerable<_anon> невозможна, так что .AsEnumerable() - это единственный путь.

Спасибо всем, кто ответил, что помогли мне собрать это вместе. =)

.
16
ответ дан 24 November 2019 в 16:21
поделиться
[

] Это просто милейший и кратчайший путь к IEnumerable. Если вы посмотрите на него в рефлекторе, то увидите, что он ничего не делает, кроме как возвращает объект как IEnumerable.[

] [

]Из MSDN:[

] [
] [

]The AsEnumerable(Of Источник)(IEnumerable(Of TSource)) метод не имеет никакого эффекта, кроме как изменить тип источника компилируемого времени от типа, который применяет IEnumerable(of T) to IEnumerable(of T) себя.[

] [
]
3
ответ дан 24 November 2019 в 16:21
поделиться

Как вы говорите, если тип уже реализует IEnumerable, то функциональной разницы между приведением к интерфейсу и вызовом метода AsEnumerable на самом деле нет.

Моя догадка, и это всего лишь догадка, заключается в том, что вызов AsEnumerable улучшает читабельность и сохраняет беглость сигнатуры других методов расширения LINQ:

var query = ((IEnumerable<YourType>)yourCollection).Select(x => x.YourProperty);

// vs

var query = yourCollection.AsEnumerable().Select(x => x.YourProperty);

Он также позволяет типам, которые не реализуют IEnumerable - например, - иметь свою версию расширения DataTable - иметь свою версию AsEnumerable. Это позволяет продолжить использование того же паттерна в запросах против этих типов - даже если это другой метод AsEnumerable, - не беспокоясь о том, реализует ли данный тип на самом деле IEnumerable.

2
ответ дан 24 November 2019 в 16:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: