gpt4 book ai didi

c# - 将表达式与运算符 && 组合

转载 作者:行者123 更新时间:2023-11-30 12:15:07 25 4
gpt4 key购买 nike

我的类(class)有点像 Linq To Sql Where条款。

它从表达式树构建一系列操作。

表达式树是一个 Expression<Func<bool>> (即没有参数但返回 bool 值的 lambda)

conditionBuilder.BuildCondition(() => x != 3 && y != 5);

该类适用于 normal表达式如上例,但现在我需要组合表达式的功能。

我添加了 And, Or 之类的方法

var exp1 = () => x != 3;
var exp2 = () => y != 5;
var exp = ConditionBuilder.And(exp1, exp2);

但组合多个表达式时会变得复杂。

我想写

var exp = exp1 && exp2;

但是因为我不能直接重载运算符 && 我需要找到一些其他的解决方案。棘手的部分是结果操作没有按位运算符的 bool 重载。即 exp1 和 exp2 的结果是 int 而不是 bool。 (我可以通过添加 != 0 来解决这个问题)

所以我现在的问题是:

  • 如果我让运算符 & 成为逻辑表达式(即 AndAlso),会不会造成混淆?
  • 运算符 && 如果我重载 &/true/false 将起作用,但这也会创建隐式 bool 转换。我知道隐式 bool 转换是你想在 C++ 中避免的事情,但我不确定它对 C# 有何影响。另外,重写的 true 和 false 是否应该计算表达式? (即 if (exp1) 应该做什么?)

编辑:我已经有了这样的工作代码:

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 (真正的格式是另外一回事,但你明白了)

问题是其他格式没有按位运算符的 bool 重载。这意味着 () => true & false转换为 True BITAND False这不是一个有效的表达式,因为它返回一个 int 而不是一个 bool 值。

如果我重载 & 意味着 AndAlso

exp1 & exp2

是一个有效的表达式但是

() => x != 3 & y != 5

不是。

我的第二个问题是,隐式转换为 bool 是否会像在 C++ 中那样在 C# 中导致问题。

最佳答案

我会重载 & 运算符。这不会混淆,因为 & 可以是逻辑的或按位的,具体取决于上下文。

要重载 & 运算符,您必须为重载运算符使用包装类(例如 ConditionBuilder)。

您可以在 true 运算符的文档中看到重载各种运算符的完整示例,包括 &http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx .


一个使用 ConditionBuilder 来演示重载 & 运算符的简单示例。

void Main ()
{
int x = 1;
int y = 1;

var exp1 = new ConditionBuilder (() => x != 3);
var exp2 = new ConditionBuilder (() => y != 5);
var exp3 = exp1 & exp2;

Console.WriteLine (exp3.Execute ());
}

public class ConditionBuilder
{
private readonly Expression<Func<bool>> _filter;

public ConditionBuilder(Expression<Func<bool>> filter) {
_filter = filter;
}

public bool Execute() {
return _filter.Compile()();
}

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)));
}

public static ConditionBuilder operator & (ConditionBuilder left, ConditionBuilder right) {
// Note this could confuse users for the problem discussed below.
// Consider using Expression.And instead of AndAlso
return ConditionBuilder.And(left, right);
}

public static ConditionBuilder operator | (ConditionBuilder left, ConditionBuilder right) {
// Note this could confuse users for the problem discussed below.
// Consider using Expression.Or instead of OrElse
return ConditionBuilder.Or(left, right);
}
}

我会小心地将短路运算符(AndAlsoOrElse)与 &| 用作给定 Foo() & Bar(),当 Foo 返回 false 时,Bar 将不会被调用,这将是大多数用户意想不到的。


备选

将 ConditionBuilder 的 And/Or 方法更改为实例成员,并且只将右侧作为参数。

public ConditionBuilder And(ConditionBuilder right) {
return new ConditionBuilder(Expression.Lambda<Func<bool>>(Expression.AndAlso(_filter.Body, right._filter.Body)));
}

这给出了诸如 var exp3 = exp1.And(exp2); 的语法,它比原来的更简洁并且可以很好地链接 exp1.And(exp2).And(exp3 )

混合 And/Or 时必须小心,因为 exp1.Or(exp2).And(exp3) 会给你 (exp1 | exp2) & exp3而不是 exp1 | (exp2 & exp3)。这可以使用显式括号来避免,例如 (exp1.Or(exp2)).And(exp3) vs exp1.Or(exp2.And(exp3))


支持&&的问题

要支持 &&,您需要在 ConditionBuilder 中支持 truefalse 运算符,这意味着编译和执行表达式。

public static bool operator true (ConditionBuilder left) {
return left.Execute();
}

public static bool operator false (ConditionBuilder left) {
return !left.Execute();
}

当使用 LinqPAD 对此进行测试时,var exp3 = exp1 && exp2 的结果不太理想。

  1. 必须立即执行 exp1 以解决短路问题。
  2. 当 exp1 为真时,结果表达式等同于:
    var exp3 = () => x != 3 && y != 5
  3. 当 exp1 为假时,结果表达式等同于:
    var exp3 = () => x != 3

关于c# - 将表达式与运算符 && 组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8244206/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com