Разница между интерфейсами IQueryable, ICollection, IList и IDictionary

Я пытаюсь понять разницу между интерфейсами IQueryable, ICollection, IList и IDictionary, которые более быстры для базовых операций, таких как итерации, индексирование, запросы и многое другое.

какой класс, такой как Collection, List, Dictionary и т. д., было бы хорошо начать с этих интерфейсов и когда мы должны использовать эти классы. Основные преимущества использования этих классов над другими.

Я пытался читать другие посты с похожими вопросами, но ничего не ответил на мои полные вопросы. Спасибо за помощь.

3 ответа

Решение

Все эти интерфейсы наследуются от IEnumerable, что вы должны убедиться, что понимаете. Этот интерфейс в основном позволяет использовать класс в foreach заявление (в C#).

  • ICollection - это самый простой из перечисленных вами интерфейсов. Это перечислимый интерфейс, который поддерживает Count и все.
  • IList - это все, чем является ICollection, но он также поддерживает добавление и удаление элементов, извлечение элементов по индексу и т. Д. Это наиболее часто используемый интерфейс для "списков объектов", который я не знаю.
  • IQueryable - это перечислимый интерфейс, который поддерживает LINQ. Вы всегда можете создать IQueryable из IList и использовать LINQ to Objects, но вы также найдете IQueryable, используемый для отложенного выполнения операторов SQL в LINQ to SQL и LINQ to Entities.
  • IDictionary - это другое животное в том смысле, что это отображение уникальных ключей к значениям. Он также перечислим в том смысле, что вы можете перечислять пары ключ / значение, но в противном случае он служит другой цели, чем другие, перечисленные вами.

Документация MSDN для каждого из них является достойной, поэтому я бы начал с того, чтобы завершить ваше понимание.

Я заметил несколько проблем в ответе @gunny229 выше, поэтому я пишу этот пост. Я упомянул об этих проблемах в области комментариев своего поста. Чтобы исправить этот пост, мне пришлось бы переписать почти весь пост, поэтому я подумал о создании своего. Я не собираюсь полностью отвечать на вопросы OP, но хочу указать на разницу между IQueryable и IEnumerable при использовании LINQ to SQL.

Я создал следующую структуру в БД (скрипт DDL):

CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)

Вот скрипт вставки записи (DML скрипт):

INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO

Теперь моей целью было просто получить топ-2 записи от Employee таблица в базе данных. Итак, я добавил элемент модели данных ADO.NET в консольное приложение, указывая на Employee таблица в моей базе данных и начал писать запросы LINQ.

Код для IQueryable маршрута:

using (var efContext = new EfTestEntities())
{
    IQueryable<int> employees = from e in efContext.Employees  select e.Salary;
    employees = employees.Take(2);

    foreach (var item in employees)
    {
        Console.WriteLine(item);
    }
}

Когда я начал запускать эту программу, я также запустил сеанс профилировщика SQL-запросов на своем экземпляре SQL Server, и вот сводная таблица выполнения:

  1. Общее количество выполненных запросов: 1
  2. Текст запроса: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

Это просто IQueryable достаточно умен, чтобы применить Top (2) предложение на стороне сервера базы данных, поэтому он переносит только 2 из 5 записей по проводам. Дальнейшая фильтрация в памяти вообще не требуется на стороне клиентского компьютера.

Код для IEnumerable маршрута:

using (var efContext = new EfTestEntities())
{
    IEnumerable<int> employees = from e in efContext.Employees  select e.Salary;
    employees = employees.Take(2);

    foreach (var item in employees)
    {
        Console.WriteLine(item);
    }
}

Резюме выполнения в этом случае:

  1. Общее количество выполненных запросов: 1
  2. Текст запроса, захваченный в профилировщике SQL: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

Теперь дело в том, IEnumerable принес все 5 записей, присутствующих в Salary таблицы, а затем выполнил фильтрацию в памяти на клиентском компьютере, чтобы получить 2 верхние записи. Таким образом, дополнительные данные (в данном случае 3 дополнительные записи) были переданы по проводам без необходимости.

IQueryable,IList,IDictionary,ICollection наследует интерфейс IEnumerable. Все интерфейсы коллекции типов будут наследовать интерфейс IEnumerable.

Различия между IEnumerable и IQueryable IEnumerable: -при выполнении запроса, который возвращает тип IEnumerable. Сначала IEnumerable выполняет первый запрос, а затем выполняет подзапросы, написанные для этого запроса.

Пример:-Если вы хотите получить топ-10 записей о населении из определенной страны, тогда запрос, который мы будем использовать в LinQ:

IEnumerable _Population= из s в Индии select s.population;// Первый запрос _Population=_Population.take(10);// Второй запрос

Теперь, если мы выполним этот запрос, сначала будет выполнен первый запрос, IEnumerable получит записи всего населения с сервера sql, затем он сохранит данные в памяти In Process, а затем выполнит топ-10 населения в следующем запросе.(Выполнение происходит два раза на сервере sql).

если мы выполним тот же запрос с помощью IQueryable.

IQueryable _Population = из s в Индии select s.population;// Первый запрос _Population=_Population.take(10);// Второй запрос

в этом IQueryable он будет выполнять два запроса одновременно в том смысле, что он получит совокупность, которая входит в топ-10 в одном запросе, вместо того, чтобы получать данные и снова фильтровать первые 10 (одноразовое выполнение на сервере sql),

Заключение для IQueryable и IEnumerable

  1. Если вы пишете запрос к данным в базе данных, используйте IQueryable.
  2. Если вы запрашиваете данные, находящиеся в процессе, используйте IEnumerable. IEnumerable имеет методы GetEnumerator(),Current() и MoveNext().
Другие вопросы по тегам