我试图找出在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的两个属性。
这似乎应该很简单,但我似乎无法通过试验或谷歌搜索来找到正确的语法。
答案 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(); }
}
}
}