Предикаты (Predicates) в C# или программирование с удовольствием

ru-RU | создано: 22.09.2010 | опубликовано: 21.04.2014 | обновлено: 01.01.2018 | просмотров за всё время: 8323

Есть в языке С# свои вкусности, или как обычно выражаются программисты - "синтаксический сахар". Так вот об этом "синтаксическом сахаре" я и хочу поведать.

Сразу же начну с примера. Давайте допустим, что Вас есть коллекция каких-нибудь объектов. В моём примере – это будет коллекция машин (Car) в гараже. Вот как он выглядит:

public class Car
{
    public int WheelSize { get; set; }
    public string ColorName { get; set; }
    public int DoorsCount { get; set; }
    public bool IsBroken { get; set; }

    public override string ToString()
    {
        return string.Format("Car: {0}, {1}, {2}", ColorName, WheelSize.ToString(), IsBroken.ToString());
    }
}

Тип проекта для примера буду использовать “Console Application”, а для того чтобы вывод на консоль был “красивым” пришлось переопределить ToString().

Перед тем как экспериментировать с машинами в гараже, давайте наполним коллекцию объектами:

private static List<Car> CreateGarage()
{
    List<Car> cars = new List<Car>()
    {
        new Car(){ ColorName="Синий", DoorsCount=4, IsBroken=false, WheelSize=15},
        new Car(){ ColorName="Мокрый асфальт", DoorsCount=4, IsBroken=true, WheelSize=18},
        new Car(){ ColorName="Бежевый", DoorsCount=3, IsBroken=false, WheelSize=22},
        new Car(){ ColorName="Красный", DoorsCount=4, IsBroken=true, WheelSize=22},
        new Car(){ ColorName="Бежевый", DoorsCount=3, IsBroken=false, WheelSize=17},
        new Car(){ ColorName="Красный", DoorsCount=4, IsBroken=false, WheelSize=19},
    };
    return cars;
} 

Вот теперь можно и в “машинки поиграть”. Давайте предположим, что нам нужно выбрать все машины в гараже, которые имеют повреждения (IsBroken) и не могут покинуть гараж. Первый способ найти машины – это создать такой метод:

private static List<Car> GetBrokenCars(List<Car> garage)
{
    List<Car> founded = new List<Car>();
    foreach (Car item in garage)
    {
    if (item.IsBroken)
    {
        founded.Add(item);
    }
    }
    return founded;
}

Надеюсь, что не нужно пояснять код этого метода, всё просто. Используем метод:

foreach (Car item in GetBrokenCars(Garage))
{
    Console.WriteLine(item.ToString());
}

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

-------- 1 способ -------------
Car: Мокрый асфальт, 18, True
Car: Красный, 22, True

Ну, а теперь покажу второй способ, который уже будет использовать предикат (FoundCar). Вот так это страшное слово выглядит в коде:

private static bool FoundCar(Car car)
{
    if (car.IsBroken)
    {
        return true;
    }
    else
    {
        return false;
    }
}

А вот так его можно использовать:

foreach (Car item in Garage.FindAll(FoundCar))
{
    Console.WriteLine(item.ToString());
}

Не трудно догадаться, что результат работы метода будет выглядеть также:

-------- 2 способ --------------
Car: Мокрый асфальт, 18, True
Car: Красный, 22, True

Теперь немного лирики. В данном примере использование предиката не очень сильно уменьшает количество строк кода. Но могу заверить Вас, что в некоторых случаях (в более серьёзных программных проектах) использование предикатов очень существенно упрощает жизнь. Проверено на практике.

Ну, и в конце статейки, приведу еще метод Main, дабы не выкладывать файл такого простого проекта для скачивания.

static void Main(string[] args)
{
    List<Car> Garage =  CreateGarage();
    Console.WriteLine("-------- 1 способ -------------");
    foreach (Car item in GetBrokenCars(Garage))
    {
        Console.WriteLine(item.ToString());
    }
    Console.WriteLine("-------- 2 способ --------------");
    foreach (Car item in Garage.FindAll(FoundCar))
    {
        Console.WriteLine(item.ToString());
    }
    Console.WriteLine("--------------------------------");
}

Примечание: да какие к черту примечания… Всё так просто…