배열에서 여러 LINQ 표현식을 결합하십시오
-
03-07-2019 - |
문제
나는 SO와 같은 기능 목록을 결합하려고합니다.
나는 이것을 가지고있다:
Func<int, bool>[] criteria = new Func<int, bool>[3];
criteria[0] = i => i % 2 == 0;
criteria[1] = i => i % 3 == 0;
criteria[2] = i => i % 5 == 0;
그리고 나는 이것을 원한다 :
Func<int, bool>[] predicates = new Func<int, bool>[3];
predicates[0] = i => i % 2 == 0;
predicates[1] = i => i % 2 == 0 && i % 3 == 0;
predicates[2] = i => i % 2 == 0 && i % 3 == 0 && i % 5 == 0;
지금까지 다음 코드가 있습니다.
Expression<Func<int, bool>>[] results = new Expression<Func<int, bool>>[criteria.Length];
for (int i = 0; i < criteria.Length; i++)
{
results[i] = f => true;
for (int j = 0; j <= i; j++)
{
Expression<Func<int, bool>> expr = b => criteria[j](b);
var invokedExpr = Expression.Invoke(
expr,
results[i].Parameters.Cast<Expression>());
results[i] = Expression.Lambda<Func<int, bool>>(
Expression.And(results[i].Body, invokedExpr),
results[i].Parameters);
}
}
var predicates = results.Select(e => e.Compile()).ToArray();
Console.WriteLine(predicates[0](6)); // Returns true
Console.WriteLine(predicates[1](6)); // Returns false
Console.WriteLine(predicates[2](6)); // Throws an IndexOutOfRangeException
내가 뭘 잘못하고 있는지 아는 사람 있나요?
해결책
이것은 내가 이것에 대해 거의 알지 못한 것처럼 추측 이었지만, 이것은 그것을 고치는 것 같습니다.
Func<int, bool>[] criteria = new Func<int, bool>[3];
criteria[0] = i => i % 2 == 0;
criteria[1] = i => i % 3 == 0;
criteria[2] = i => i % 5 == 0;
Expression<Func<int, bool>>[] results = new Expression<Func<int, bool>>[criteria.Length];
for (int i = 0; i < criteria.Length; i++)
{
results[i] = f => true;
for (int j = 0; j <= i; j++)
{
int ii = i;
int jj = j;
Expression<Func<int, bool>> expr = b => criteria[jj](b);
var invokedExpr = Expression.Invoke(expr, results[ii].Parameters.Cast<Expression>());
results[ii] = Expression.Lambda<Func<int, bool>>(Expression.And(results[ii].Body, invokedExpr), results[ii].Parameters);
}
}
var predicates = results.Select(e => e.Compile()).ToArray();
핵심은 'II'와 'JJ'를 소개하는 것입니다 (아마도 한 가지 문제 만 시도하지 않았을 것입니다). 나는 당신이 람다 내부에서 변이 가능한 변수를 캡처하고 있다고 생각합니다. 따라서 마침내 그것을 참조하면 원래 값보다는 나중에 돌이 많은 값을 볼 수 있습니다.
다른 팁
표현을 잡아 당길 필요가 없습니다 ...
Func<int, bool>[] criteria = new Func<int, bool>[3];
criteria[0] = i => i % 2 == 0;
criteria[1] = i => i % 3 == 0;
criteria[2] = i => i % 5 == 0;
Func<int, bool>[] predicates = new Func<int, bool>[3];
predicates[0] = criteria[0];
for (int i = 1; i < criteria.Length; i++)
{
//need j to be an unchanging int, one for each loop execution.
int j = i;
predicates[j] = x => predicates[j - 1](x) && criteria[j](x);
}
Console.WriteLine(predicates[0](6)); //True
Console.WriteLine(predicates[1](6)); //True
Console.WriteLine(predicates[2](6)); //False
제휴하지 않습니다 StackOverflow