在 C# 中评估布尔表达式

Evaluating boolean expression in C#

我编写了下面的代码来评估布尔表达式。表达式以对象的形式编码。

这是我查看代码并思考的时刻之一:我确信有更好的编码方法,使用更少的布尔变量但看不到正确的方法。有什么帮助吗?已编写单元测试并通过各种输入。

if (tree == null || !tree.IsActive || tree.FilterNodes == null)
{
     return false;
}
var result = false;
foreach (var filter in tree.FilterNodes.Where(a => a.IsActive && a.ConditionNodes != null))
{
     var tempBool = false;
     foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
     {
          if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
          {
               var value = values[condition.FieldName];
               if (filter.LogicalOperator == LogicalOperator.Or && ApplyCondition(condition.ConditionOperator, value, condition.FieldValue))
               {
                   tempBool = true;
                   break;
               }
               else if (filter.LogicalOperator == LogicalOperator.And)
               {
                   tempBool = ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);
                   if (!tempBool)
                   {
                        break;
                   }
               }
               else
               {
                   tempBool = false;
               }
           }
           else if (!string.IsNullOrWhiteSpace(condition.FieldName) && filter.LogicalOperator == LogicalOperator.And)
           {
                tempBool = false;
           }
     }
     result = tempBool;
     if (!result)
     {
          break;
     }
}
return result;

您可以在循环中设置 tempBool = false 第一件事并省略 else 和最后 else if:

 foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
 {
      tempBool = false;
      if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
      {
           var value = values[condition.FieldName];
           if (filter.LogicalOperator == LogicalOperator.Or && ApplyCondition(condition.ConditionOperator, value, condition.FieldValue))
           {
               tempBool = true;
               break;
           }
           else if (filter.LogicalOperator == LogicalOperator.And)
           {
               tempBool = ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);
               if (!tempBool)
               {
                    break;
               }
           }
       }
 }

编辑

它变得更加简单:

 foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
 {
      tempBool = false;
      if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
      {
           var value = values[condition.FieldName];
           tempBool == ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);

           if ((filter.LogicalOperator == LogicalOperator.And && !tempBool) || (filter.LogicalOperator == LogicalOperator.Or && tempBool))
           {
                break;
           }
       }
 }

在如果你需要ApplyCondition为真然后将tempBool设置为true(也是ApplyCondition的结果)。在 else 中,如果将 tempBool 设置为 ApplyCondition 的结果。这意味着您可以首先将 tempBool 设置为 ApplyCondition 的结果。现在你只需要决定是否需要休息。

采用更 o-o 的方法,我认为您的运算符需要由继承自基础 class 的 classes 定义。基础 class 将具有您的操作员实现的抽象 Evaluate 方法。然后,您可以使用 o-o 多态性来评估您的运算符,而无需担心内部细节。实际上,您已经开始使用简单的解释器了。

编写布尔解释器的一种更正式的方法是考虑由 正式语法 生成的布尔表达式并编写 解析器 和一个解释器。解释器可以实现为 抽象语法树 .

我做了一个开源库来实现这个,如果你想看一下GitHub