同じIEnumerableに最大5つのFuncを累積的に適用するための良い方法を見つけようとしています。これが私が思いついたものです:
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;
}
これらは累積的に適用されると思いましたが、結果から、実際には最後の1つ(DepartmentFilter)を適用しているだけであることがわかります。
2 ^ 4の可能な組み合わせがあるので、ブルートフォースif/elsesが機能しない場合。(対応するキーが辞書に存在する場合にのみ、特定のラムダをANDで使用したい。)
編集:これが私が受け入れた解決策ですが、評価されると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;
}
編集:これが、友人でありメンターであるChrisFlatherからStackOverflowExceptionが発生した理由の非常に優れた説明です-
無限再帰が発生する理由を理解するための重要なことは、ラムダ内のシンボルがいつ解決されるかを理解することです(つまり、実行時であり、定義時ではありません)。
この単純化された例を見てください:
Func<int, int> demo = (x) => x * 2;
Func<int, int> demo2 = (y) => demo(y) + 1;
demo = demo2;
int count = demo(1);
定義時に静的に解決された場合、これは機能し、次のようになります。
Func<int, int> demo2 = (y) => (y * 2) + 1;
Int count = demo2(1);
ただし、demo2に埋め込まれたデモが実行時に何をするかを実際に理解しようとはしません。実行時に、demo2はdemoに再定義されます。基本的に、コードは次のようになります。
Func<int, int> demo2 = (y) => demo2(y) + 1;
Int count = demo2(1);