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

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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

если мы выполним тот же запрос, используя IQueryable.

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

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

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

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

Ответ 3

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

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

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

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

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 в базе данных. Итак, я добавил элемент модели данных Entity Data 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 Query на моем экземпляре SQL Server и вот сводка о выполнении:

  • Общее количество запущенных запросов: 1
  • Текст запроса: 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
  • Текст запроса, захваченный в профилировщике SQL: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

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