lambda中的C#匿名函数

时间:2017-08-03 10:31:32

标签: c# lambda anonymous-function

我试图找出在linq .Where()调用的lambda中使用匿名函数的语法。

我使用Where筛选列表中的某些项目。

我希望过滤逻辑的每个部分都在Where里面。该逻辑仅在过滤器内部有用,因此我不想在外部定义任何函数。

这是一个简化的&一般化的例子:

var filtered = myEnumerable.Where(item =>
    item.PropertyA == 1 ||
    item.PropertyB == 2 ||
    item => 
    {
        var heavyResult = GetStuff(item); // Some heavyweight processing
        return heavyResult.IsSomethingTrue() && heavyResult.IsSomethingElseTrue();
    });

所以我希望Where()中的第三行是一个匿名函数,它取项并返回一个布尔值。

此外,在对PropertyA和PropertyB进行检查后调用的函数旨在限制必须调用GetStuff(),如果这些轻量级比较中的任何一个已经评估为true。

我不能全部内联,因为我需要评估来自heavyResult的两个属性。

这似乎应该很简单,但我似乎无法通过试验或谷歌搜索来找到正确的语法。

2 个答案:

答案 0 :(得分:2)

  

我无法全部内联,因为我需要评估来自heavyResult的两个属性。

你可以内联完成,只需要在{}中包装整个内容并使用return关键字。

var filtered = myEnumerable.Where(item =>
    {
        var test = item.PropertyA == 1 || item.PropertyB == 2;
        if(test)
          return true; 
        var heavyResult = GetStuff(item); // Some heavyweight processing
        return heavyResult.IsSomethingTrue() && heavyResult.IsSomethingElseTrue();
    });

说实话 - 做一些即使是那么简单的内联也可能是错误的选择。将其解压缩为具有有意义名称的函数,并且您的代码是自我记录的

var filtered = myEnumerable.Where(ADescriptiveNamedFunctionSelfDocumentsYourCode);

答案 1 :(得分:0)

首先,多线lambda是一个非常糟糕的主意。

它们的目的是简单的功能表示f(x)= ...

你不能按照你想的方式这样做,因为你首先要调用一个函数,捕获它的结果,&然后在该对象上调用2种不同的方法。

您可以通过将委托移出lambda来更简单地完成此操作。

最新版本的C#支持本地功能,这可能是您想要的。但是你仍然可以使用C#6中的匿名函数来完成这项工作。

我还展示了如何使用HeavyResult中的其他方法或扩展方法来改变HeavyResult是不可行的。

在下面的代码中,您只能使用

中的一个选项
validator(item) ||
GetStuff(item).IsAllTrue() ||
GetStuff(item).IsAllTrueExt()

这是完整的代码:

public static class Program
{
    static void Main(string[] args)
    {
        var myEnumerable = new List<int>() { 1, 2, 3, 4, 5 };

        Predicate<int> validator;
        validator = delegate (int item)
        {
            var heavyResult = GetStuff(item);
            return heavyResult.IsSomethingTrue() && heavyResult.IsSomethingElseTrue();
        };

        var filtered = myEnumerable.Where(item =>
        item >= 1 ||
        item <= 200 ||
        validator(item) ||
        GetStuff(item).IsAllTrue() ||
        GetStuff(item).IsAllTrueExt()
        );
    }

    public static bool IsAllTrueExt(this HeavyResult hr)
    {
        { return hr.IsSomethingTrue() && hr.IsSomethingElseTrue(); }
    }

    public static HeavyResult GetStuff(int item)
    {
        return new HeavyResult(item);
    }

    public class HeavyResult
    {
        public HeavyResult(int value)
        {
            Value = value;
        }

        int Value { get; }

        public bool IsSomethingTrue()
        {
            { return Value >= 5; }
        }

        public bool IsSomethingElseTrue()
        {
            { return Value <= 50; }
        }

        public bool IsAllTrue()
        {
            { return IsSomethingTrue() && IsSomethingElseTrue(); }
        }

    }
}