2017-08-03 74 views
1

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

我正在使用“从哪里”筛选列表中的某些项目。

我希望过滤器逻辑的每个部分在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(); 
    }); 

所以我想在哪里第三行()是一个匿名函数取项目,并返回一个布尔值。

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

我不能这样做所有内联,因为我需要评估来自heavyResult的两个属性。

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

+0

其实我怀疑这是否是真实的情景?你可以用更简单的方法做到这一点 –

+0

虽然你可以做到这一点,但我怀疑你应该*,因为它只是增加了记录函数功能的必要性。取而代之的是提取一个具有描述性名称的命名方法,以确定该方法中发生了什么。 – HimBromBeere

回答

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); 
+0

谢谢。我确实得到它与这种风格的工作。对于PropertyA和PropertyB检查,我看起来更加丑陋。看来应该有一种方法将GetStuff/heavyResult部分捆绑到一个匿名函数中。 – Tom

+0

@汤姆 - 有。它在这个答案。 – Jamiec

+0

谢谢大家。我赞赏关于应该如何尝试这样做的意见,我认为在我的真实例子中,我将不得不定义一个外部方法来执行过滤逻辑。 就我上面的具体问题而言,纯粹从语法上来说,我想答案是 - 不,没有办法像这样定义一个内联匿名函数? – Tom

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(); } 
     } 

    } 
}