передать лямбду в качестве делегата в метод - PullRequest
0 голосов
/ 07 июня 2018

Я новичок в c #, и я очень растерялся из-за делегатов.Я знаю, что мы должны использовать их, как только нам понадобится передать методам одинаковых сигнатур с разными условиями.

У меня есть класс:

public class Turbines
{
    public string Turname { get; set; }
    public double TurID { get; set; }

    public double Production { get; set; }

    public double Availability { get; set; }
}

Я инициализирую этот класс:

List<Turbines> newTur = new List<Turbines>
{
    new Turbines { Turname="inUK", TurID=1245, Production=1452.22, Availability=52.12 },
    new Turbines { Turname="InUS", TurID=125, Production=1052.22, Availability=92.12 }
};

Теперь, если я хочу получить Turnames с доступностью> 90% и в следующий раз Turnames с производством> 1300, я могу иметь метод и передать ему делегата.

Может кто-нибудь сказать мне, каксоздать метод и делегировать?

Ответы [ 5 ]

0 голосов
/ 07 июня 2018

В этом случае вы хотите получить 2 разных результата из одной коллекции (списка) в 2 разных времени.Самый простой способ сделать это - определить методы в этой коллекции, которые будут возвращать вам результаты, например, один метод, который возвращает вам результаты, доступность которого> 90%, и другой, производство которого> 1300. Но при этом вы теряете динамическую динамику.характер запроса и насыщенность коллекции методами - каждый раз, когда вам нужно изменить этот критерий, вам нужно изменить коллекцию и добавить новый метод.

Чтобы решить эту проблему, у нас есть делегаты, которые просто работают как указатель на функцию.Таким образом, в основном вместо того, чтобы писать новые методы в контейнере, вы передаете фрагмент кода как объект, который определяет, какие элементы выбрать из вашей коллекции.Этот подход называется «инверсией управления».

Итак, здесь для доступности вы вызываете List.Where и передаете ему функцию, которая сообщает ему, включать ли конкретный объект Turbines или нет.

Func<Turbines, bool> availabilityFunc = delegate (Turbines t)
{
    return t.Availability > 90;
};
var result = newTur.Where(availabilityFunc);

Метод Where - это метод фильтрации, который выбирает определенные элементы в контейнере на основе переданного предиката.Здесь предикатом является делегат типа Func, который в основном является функциональным объектом, внутри которого я инкапсулировал логику выбора.

Теперь вместо того, чтобы делать все это, вы можете просто передать лямбда-выражение в виде ярлыка.

var result = newTur.Where( t => t.Availability > 90; );
0 голосов
/ 07 июня 2018

Вам нужен делегат Predicate<Turbine>.Этот делегат представляет метод со следующей подписью:

bool Method(Turbine turbine)

Вы должны написать метод, подобный этому:

public List<Turbine> GetTurbines(Predicate<Turbine> predicate) {
    var list = new List<Turbine>();
   foreach (var turbine in newTur) {
       if (predicate(turbine)) {
           list.Add(turbine);
       }
   }
   return list;
}

Обратите внимание на часть if (predicate(turbine)), там я в основном вызываю методэто передается внутрь. Если метод возвращает true, я добавляю его в список.

Таким образом, вы можете передать метод, подобный этому, в GetTurbines, чтобы получить все турбины с доступностью более 90:

bool Over90Availability(Turbine turbine) {
   return turbine.Availability > 90;
}
// ...
var list = GetTurbines(Over90Availability);

Вы можете переписать метод с помощью лямбда-выражения:

var list = GetTurbines(turbine => turbine.Availability > 90);

Слово turbine перед => является именем параметра.Все, что после => - это возвращаемое вами значение.

Надеюсь, вы понимаете, как это работает сейчас.

Фактически, вы только что заново изобрели колесо, создав GetTurbine.Существует метод расширения, называемый Where в System.Linq.Enumerable, который в основном является тем же:

var list = newTur.Where(turbine => turbine.Availability > 90).ToList();
0 голосов
/ 07 июня 2018

Делегаты - это способ передачи методов (включая лямбды) в качестве параметров:

   var selection = MyFilter( newTur , t => t.Availability > 90);


IENumerable<Turbines> MyFilter(IENumerable<Turbines> source, Func<Turbines, bool> filter)
{
   return source.Where(filter);
}

Обратите внимание, что вещи становятся немного более читабельными, когда вы отбрасываете s из Turbines.Объект является единственным Turbine.

А лямбда-это просто способ написать встроенную функцию.Вы также можете вызвать MyFilter следующим образом:

 var selection2 = MyFilter( newTur , ProductionOver1300);


bool ProductionOver1300(Turbines t)  // matches  Func<Turbines, bool> 
{
   return t.Production > 1300;
} 

Синтаксис хитрый, bool b = ProductionOver1300(aTurbine) - вызов обычной функции.Оставьте параметры для получения делегата: Func<Turbines, bool> f = ProductionOver1300;.f теперь является переменной делегата, и вы можете сделать bool b = f(aTurbine);

0 голосов
/ 07 июня 2018

Не совсем понятно, о чем вы спрашиваете, поэтому я попытаюсь объяснить некоторые основные понятия.

Прежде всего, поскольку у вас есть List<Turbines> и List<T> орудия IEnumerable<T>, вы можетеиспользуйте .Where метод расширения .Этот метод действует на IEnumerable<TSource> и принимает в качестве аргумента предикат с подписью Func<TSource, bool>.Вы можете передать этот аргумент несколькими способами, более распространенными из которых являются 1) с лямбда-выражением и 2) с классическим методом:

public class YourClass
{
    public void YourMethod()
    {
        List<Turbines> newTur = new List<Turbines>
        {
            new Turbines { Turname = "inUK", TurID = 1245, Production = 1452.22, Availability = 52.12 },
            new Turbines { Turname = "InUS", TurID = 125, Production = 1052.22, Availability = 92.12 }
        };

        // 1) passing filter as a lambda
        IEnumerable<Turbines> filteredListWithLambda = newTur.Where(t => t.Availability > 90.0 && t.Production > 1300);

        // 2) passing filter as a method
        IEnumerable<Turbines> filteredListWithMethod = newTur.Where(Filter);
    }

    private bool Filter(Turbines turbines)
    {
        return turbines.Availability > 90.0 && turbines.Production > 1300;
    }
}

Если вы хотите изменить значения вашего фильтра, у вас будетдолжны получить в YourMethod эти значения и вставить их в фильтр, например:

public class YourClass
{
    public void YourMethod(double availability, int production)
    {
        List<Turbines> newTur = new List<Turbines>
        {
            new Turbines { Turname = "inUK", TurID = 1245, Production = 1452.22, Availability = 52.12 },
            new Turbines { Turname = "InUS", TurID = 125, Production = 1052.22, Availability = 92.12 }
        };

        IEnumerable<Turbines> filteredListWithLambda = newTur.Where(t => t.Availability > availability && t.Production > production);
    }
}
0 голосов
/ 07 июня 2018

Просто примените этот кусок кода

var result = newTur.Where(each => each.Availability > 90 && each.Turnames > 1300);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...