У меня есть класс, который работает немного как предложение Linq To Sql Where
.
Он строит последовательность операций из дерева выражений.
Дерево выражений представляет собой Expression<Func<bool>>
(т.е. лямбда без аргументов, которая возвращает логическое значение)
conditionBuilder.BuildCondition(() => x != 3 && y != 5);
Класс отлично работает для normal
выражений, как в примере выше, но теперь мне нужна функциональность для объединения выражений.
Я добавил And, Или такие методы, как
var exp1 = () => x != 3;
var exp2 = () => y != 5;
var exp = ConditionBuilder.And(exp1, exp2);
но это усложняется при объединении нескольких выражений.
Я хотел бы написать
var exp = exp1 && exp2;
но поскольку я не могу напрямую перегрузить оператор &&, мне нужно найти другое решение.
Сложность в том, что в результирующих операциях нет логической перегрузки для побитовых операторов. то есть результат exp1 и exp2 - это int, а не bool. (Я могу обойти это, добавив != 0
)
Итак, мои вопросы сейчас:
- Будет ли сбивающим с толку, если я позволю оператору & быть логическим выражением (т.е. AndAlso)?
- Оператор && будет работать, если я перегружу & / true / false, но это также создаст неявное логическое преобразование. Я знаю, что неявное логическое преобразование - это то, чего вы хотите избежать в C ++, но я не уверен, насколько это важно в C #. Кроме того, должны ли переопределенные истина и ложь исказить выражение? (то есть что
if (exp1)
должен делать?)
Edit:
У меня уже есть рабочий код, подобный этому:
public class ConditionBuilder
{
private readonly Expression<Func<bool>> _filter;
public ConditionBuilder(Expression<Func<bool>> filter) {
_filter = filter;
}
public static ConditionBuilder And(ConditionBuilder left, ConditionBuilder right) {
return new ConditionBuilder(Expression.Lambda<Func<bool>>(Expression.AndAlso(left._filter.Body, right._filter.Body)));
}
public static ConditionBuilder Or(ConditionBuilder left, ConditionBuilder right) {
return new ConditionBuilder(Expression.Lambda<Func<bool>>(Expression.OrElse(left._filter.Body, right._filter.Body)));
}
}
Редактировать 2
уточнить вопросы.
Выражения преобразуются в другой формат. Например, () => ConditionBuilder.IntField(123) == 5
конвертируется в @123 EQ 5
(реальный формат - это нечто иное, но вы поняли)
Проблема в том, что другой формат не имеет логической перегрузки для побитовых операторов. Это означает, что () => true & false
преобразуется в True BITAND False
, которое не является допустимым выражением, поскольку возвращает целое число, а не логическое значение.
Если я перегрузить & иметь в виду AndAlso
exp1 & exp2
является допустимым выражением, но
() => x != 3 & y != 5
нет.
Мой второй вопрос был, если неявное преобразование в bool вызывает проблемы в C #, как это происходит в C ++.