You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将运行时动态生成的字符串条件转换为布尔值?

看起来你想实现的是运行时动态解析布尔表达式,这确实是游戏开发里常见的需求——比如让AI行为、触发事件依赖可配置的条件。可惜bool.TryParseConvert.ToBoolean只能处理纯"true"/"false"字符串,完全没法解析带变量和逻辑运算符的表达式,所以你的尝试走不通是正常的。

下面给你两个适配不同场景的方案,都是基于你现有知识水平可以上手的:

方案1:手动实现简单表达式解析(适合基础场景)

如果你的条件逻辑不算特别复杂(比如只有==/!=比较、&&/||逻辑、少量括号嵌套),可以自己写个轻量的解析逻辑,核心思路是把变量替换成实际值,再拆分表达式逐步计算:

using System;
using System.Collections.Generic;
using System.Linq;

public static class SimpleExpressionEvaluator
{
    public static bool Evaluate(string expression, Dictionary<string, int> variables)
    {
        // 第一步:把表达式里的变量替换成实际数值
        foreach (var kvp in variables)
        {
            expression = expression.Replace(kvp.Key, kvp.Value.ToString());
        }

        // 第二步:处理括号内的子表达式(简化版,支持一层嵌套)
        while (expression.Contains("("))
        {
            int start = expression.IndexOf("(");
            int end = expression.IndexOf(")", start);
            string subExpr = expression.Substring(start + 1, end - start - 1);
            bool subResult = CalculateSubExpression(subExpr);
            expression = expression.Replace($"({subExpr})", subResult.ToString().ToLower());
        }

        // 第三步:计算最终逻辑结果
        return CalculateSubExpression(expression);
    }

    private static bool CalculateSubExpression(string subExpr)
    {
        // 先处理&&(短路求值,遇到false直接返回)
        var andParts = subExpr.Split(new[] {"&&"}, StringSplitOptions.RemoveEmptyEntries);
        bool andResult = true;
        foreach (var part in andParts)
        {
            bool partResult = EvaluateComparison(part.Trim());
            andResult &= partResult;
            if (!andResult) break;
        }
        if (!andResult) return false;

        // 再处理||(短路求值,遇到true直接返回)
        var orParts = subExpr.Split(new[] {"||"}, StringSplitOptions.RemoveEmptyEntries);
        bool orResult = false;
        foreach (var part in orParts)
        {
            bool partResult = EvaluateComparison(part.Trim());
            orResult |= partResult;
            if (orResult) break;
        }
        return orResult;
    }

    private static bool EvaluateComparison(string comparison)
    {
        if (comparison.Contains("=="))
        {
            var parts = comparison.Split(new[] {"=="}, StringSplitOptions.RemoveEmptyEntries);
            int a = int.Parse(parts[0].Trim());
            int b = int.Parse(parts[1].Trim());
            return a == b;
        }
        else if (comparison.Contains("!="))
        {
            var parts = comparison.Split(new[] {"!="}, StringSplitOptions.RemoveEmptyEntries);
            int a = int.Parse(parts[0].Trim());
            int b = int.Parse(parts[1].Trim());
            return a != b;
        }
        // 可以扩展>、<、>=、<=等其他比较符
        throw new ArgumentException($"不支持的比较规则:{comparison}");
    }
}

使用示例:

int x = 1; int y = 2; int z = 3;
string s = "(x == 1 && y == 3) || z == 3";
var variables = new Dictionary<string, int> {{"x", x}, {"y", y}, {"z", z}};
bool b = SimpleExpressionEvaluator.Evaluate(s, variables); // 结果为true

这个方案的好处是完全自主可控,不需要额外依赖,适合你的知识水平;缺点是对复杂表达式(比如多层嵌套括号、浮点数/字符串比较)的支持需要你手动扩展。

方案2:使用C#动态编译(适合复杂场景)

如果你的条件可能涉及更复杂的逻辑(比如算术运算、字符串判断、多层嵌套),手动解析会非常麻烦,这时可以用C#的动态编译功能,把表达式转换成临时代码执行:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.CSharp;

public static class ComplexExpressionEvaluator
{
    public static bool Evaluate(string expression, Dictionary<string, object> variables)
    {
        // 生成临时C#代码:创建一个包含求值方法的类
        string code = $@"
            public static class TempEvaluator
            {{
                public static bool Compute({string.Join(", ", variables.Select(kvp => $"{kvp.Value.GetType().Name} {kvp.Key}"))})
                {{
                    return {expression};
                }}
            }}";

        // 设置编译参数:在内存中生成程序集,不写入文件
        var compilerParams = new CompilerParameters
        {
            GenerateInMemory = true,
            TreatWarningsAsErrors = false
        };

        // 编译代码
        var compiler = new CSharpCodeProvider();
        CompilerResults results = compiler.CompileAssemblyFromSource(compilerParams, code);

        // 处理编译错误
        if (results.Errors.HasErrors)
        {
            string errorMsg = string.Join("\n", results.Errors.Cast<CompilerError>().Select(e => e.ErrorText));
            throw new Exception($"表达式编译失败:\n{errorMsg}");
        }

        // 调用编译后的方法获取结果
        Type evaluatorType = results.CompiledAssembly.GetType("TempEvaluator");
        MethodInfo computeMethod = evaluatorType.GetMethod("Compute");
        object result = computeMethod.Invoke(null, variables.Values.ToArray());
        return (bool)result;
    }
}

使用示例:

int x = 1; int y = 2; int z = 3;
string s = "(x == 1 && y == 3) || z == 3";
var variables = new Dictionary<string, object> {{"x", x}, {"y", y}, {"z", z}};
bool b = ComplexExpressionEvaluator.Evaluate(s, variables); // 结果为true

这个方案支持几乎所有C#语法的布尔表达式,但要注意:

  • 需要在项目引用中添加Microsoft.CSharp程序集
  • 如果频繁执行相同表达式,建议缓存编译后的程序集,避免重复编译影响性能
  • 确保表达式来源安全(比如不要让外部用户输入恶意代码,游戏内配置的话风险较低)
为什么你之前的替换true/false方法行不通?

你之前想先校验单个条件再替换成true/false,但这种方式没法处理逻辑优先级和嵌套关系——比如(A && B) || C看起来简单,但如果是A && (B || C) && D这种多层嵌套的表达式,手动拆分替换的逻辑会变得异常复杂,很容易出错,不如直接解析或编译来得可靠。

内容的提问来源于stack exchange,提问作者Christian Dieckmann

火山引擎 最新活动