LINQ в C#: проверка элементов последовательности

При работе с различными коллекциями и списками элементов, часто бывает необходимо проверить соответствуют ли элементы этого набора данных определенным условиям. В LINQ для проверки элементов последовательностей применяются методы All, Any и Contains.

Методы All и Any

Метод All проверяет соответствуют ли все элементы коллекции заданному условию и возвращает true/false в зависимости от результата проверки. Например

int[] numbers = { 1, 3, 6, 7, 8, 11, 12 };
if (numbers.All(x => x < 20))
    Console.WriteLine("Все элементы массива меньше 20");
else
    Console.WriteLine("В массиве есть элементы больше или равный 20");

Результат

Все элементы массива меньше 20
Стоит отметить, что метод All вернет true, если коллекция пуста.

В свою очередь, метод Any проверяет соответствует ли хотя бы один элемент заданному условию:

if (numbers.Any(x => x % 2 == 0))
    Console.WriteLine("В массиве есть хотя бы одно четное число");
else
    Console.WriteLine("В массиве нет четных чисел");
В массиве есть хотя бы одно четное число
Если коллекция пуста, то метод Any вернет false

Метод Contains

Метод Contains проверяет содержится ли заданный объект в коллекции. Например,

int[] numbers = { 2, 3, 4, 5 };
if (numbers.Contains(3))
    Console.WriteLine("В массиве есть число 3");

Что касается проверки чисел, строк и т.д. с использованием Contains, то здесь все довольно прозрачно. Иначе дело обстоит с классами, например, воспользуемся нашим списком измерений:

class Program
 {
     static void Main(string[] args)
     {
          List<DataObject> objects = new List<DataObject>()
          {
              new DataObject {Name = "Утро", Value = 12.5 },
              new DataObject {Name = "День", Value = 12.1 },
              new DataObject {Name = "Вечер", Value = 80.5 },
              new DataObject {Name = "Ночь", Value = 11.3 },
              new DataObject {Name = "Утро", Value = 10.7 },
              new DataObject {Name = "День", Value = 12.1 },
              new DataObject {Name = "Вечер", Value = 80.5 },
              new DataObject {Name = "Вечер", Value = 11.3 }
          };

         DataObject test = new DataObject { Name = "Вечер", Value = 11.3 };

         
         if (objects.Contains(test))
             Console.WriteLine("В списке есть элемент");
         else
             Console.WriteLine("В списке нет элемента");

     }
 }

Результатом выполнения программы будет строка:

В списке нет элемента

Дело в том, что классы — это ссылочный тип данных. То есть, в нашем случае, переменная test содержит не сами данные по измерению, а ссылку. И именно ссылки сравнивались в приведенном выше примере, т.е. ссылка на объект test и ссылка на последний объект в списке — это разные ссылки на участки памяти где хранятся данные по объекту.

Чтобы Contains заработал как нам необходимо, нам требуется переопределить метод Equals базового типа object, например, следующим образом:

public class DataObject
{
    public string Name { get; set; }
    public double Value { get; set; }

    public override bool Equals(object obj)
    {
        return (obj == null) || (obj.GetType() != typeof(DataObject))
            ? false
            : (Name == ((DataObject)obj).Name) && (Value == ((DataObject)obj).Value);
    }
}

Теперь проверка пройдет успешно:

В списке есть элемент

Итого

Сегодня мы разобрались с тем, как проверять элементы последовательностей на соответствие каким-либо критериям с использованием методов All, Any и Contains. Для того, чтобы метод Contains мог проверять соответствие объектов по значению их свойств, необходимо переопределить у класс метод Equals.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии