将lambda作为方法的委托传递

时间:2018-06-07 10:21:05

标签: c# delegates

我是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的可用性&gt; 90%以及下次Turnames with Production&gt; 1300,我可以有一个方法并将代理传递给它。

有谁能告诉我如何创建方法和委托?

5 个答案:

答案 0 :(得分:2)

委托是一种将方法(包括lambdas)作为参数传递的方法:

   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

lambda只是一种编写内联函数的方法。您也可以这样调用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);

答案 1 :(得分:2)

您需要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);

您可以使用lambda表达式重写该方法:

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

turbine之前的单词=>是参数名称。 =>之后的所有内容都是您返回的值。

希望你现在明白这是如何运作的。

事实上,您刚刚通过创建GetTurbine重新发明了轮子。 Where中有一个名为System.Linq.Enumerable的扩展方法基本相同:

var list = newTur.Where(turbine => turbine.Availability > 90).ToList();

答案 2 :(得分:1)

您所询问的内容并不完全清楚,因此我将尝试解释一些基本概念。

首先,由于您有List<Turbines>List<T>实施IEnumerable<T>,因此您可以使用.Where extension method。 此方法作用于IEnumerable<TSource>,并将带有签名Func<TSource, bool>的谓词作为参数。你可以用几种方式传递这个参数,两个更常见的是1)用lambda和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);
    }
}

答案 3 :(得分:0)

只需简单地应用这段代码

var result = newTur.Where(each => each.Availability > 90 && each.Turnames > 1300);

答案 4 :(得分:0)

在这种情况下,您希望在2个不同的时间从同一个集合(列表)中获得2个不同的结果。执行此操作的最基本方法是定义该集合中的方法,该方法将返回结果,例如,一种方法可返回其可用性&gt;的结果。 90%和另一个其生产&gt;但是通过这样做,你正在失去请求的动态性质,并且通过方法使集合变得繁重 - 这意味着每次需要更改此条件时,您需要修改集合并添加新方法。

为了解决这个问题,我们有代表 - 它们就像一个函数指针一样工作。因此,基本上不是在容器中编写新方法,而是将一段代码作为对象传递,以确定从集合中选择哪些元素。这种方法被称为&#34;反转控制&#34;。

所以,这里为了可用性,你调用List.Where并传递一个函数,告诉它是否包含特定的Turbines对象。

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

Where方法是一种过滤方法,它根据传递的谓词选择容器中的某些元素。这里,谓词是Func类型委托 - 它基本上是一个函数对象,我在其中封装了选择逻辑。

现在,您可以简单地将lambda表达式作为快捷方式传递,而不是完成所有这些操作。

var result = newTur.Where( t => t.Availability > 90; );