我正在尝试找到一种将最多 5 个 Func 累积应用于同一个 IEnumerable 的好方法。这是我想出的:
private Func<SurveyUserView,bool> _getFilterLambda(IDictionary<string, string> filters)
{
Func<SurveyUserView, bool> invokeList = delegate(SurveyUserView surveyUserView)
{
return surveyUserView.deleted != "deleted";
};
if (filters.ContainsKey("RegionFilter"))
{
invokeList += delegate(SurveyUserView surveyUserView)
{
return surveyUserView.Region == filters["RegionFilter"];
};
}
if (filters.ContainsKey("LanguageFilter"))
{
invokeList += delegate(SurveyUserView surveyUserView)
{
return surveyUserView.Locale == filters["LanguageFilter"];
};
}
if (filters.ContainsKey("StatusFilter"))
{
invokeList += delegate(SurveyUserView surveyUserView)
{
return surveyUserView.Status == filters["StatusFilter"];
};
}
if (filters.ContainsKey("DepartmentFilter"))
{
invokeList += delegate(SurveyUserView surveyUserView)
{
return surveyUserView.department == filters["DepartmentFilter"];
};
}
return invokeList;
}
我认为它会以累积的方式应用这些,但是,我可以从结果中看到它实际上只是应用了最后一个(DepartmentFilter)。
有 2^4 种可能的组合,所以如果/否则,蛮力是行不通的。(仅当字典中存在相应的键时,我才想使用特定的 lambda。)
编辑:这是我接受的解决方案,但在评估时会导致 StackOverflowException 。有人知道为什么吗?
private Func<SurveyUserView,bool> _getFilterLambda(IDictionary<string, string> filters )
{
Func<SurveyUserView, bool> resultFilter = (suv) => suv.deleted != "deleted";
if (filters.ContainsKey("RegionFilter"))
{
Func<SurveyUserView, bool> newFilter =
(suv) => resultFilter(suv) && suv.Region == filters["RegionFilter"];
resultFilter = newFilter;
}
if (filters.ContainsKey("LanguageFilter"))
{
Func<SurveyUserView, bool> newFilter =
(suv) => resultFilter(suv) && suv.Locale == filters["LanguageFilter"];
resultFilter = newFilter;
}
if (filters.ContainsKey("StatusFilter"))
{
Func<SurveyUserView, bool> newFilter =
(suv) => resultFilter(suv) && suv.Status == filters["StatusFilter"];
resultFilter = newFilter;
}
if (filters.ContainsKey("DepartmentFilter"))
{
Func<SurveyUserView, bool> newFilter =
(suv) => resultFilter(suv) && suv.department == filters["DepartmentFilter"];
resultFilter = newFilter;
}
return resultFilter;
}
编辑:这是一个很好的解释,为什么这会导致朋友和导师 Chris Flather 的 StackOverflowException -
The important thing to understanding why the infinite recursion occurs is understanding when the symbols in a lambda are resolved (i.e. at runtime and not at definition).
Take this simplified example:
Func<int, int> demo = (x) => x * 2;
Func<int, int> demo2 = (y) => demo(y) + 1;
demo = demo2;
int count = demo(1);
If it were resolved statically at definition this would work and be the same as:
Func<int, int> demo2 = (y) => (y * 2) + 1;
Int count = demo2(1);
But it doesn’t actually attempt to figure out what the demo embedded in demo2 does until runtime – at which time demo2 has been redefined to demo. Essentially the code now reads:
Func<int, int> demo2 = (y) => demo2(y) + 1;
Int count = demo2(1);