Acesso Colaboradores

Como executar expressões matemáticas numa string em .NET

Publicado em por Gustavo Mauricio de Barros

Como executar expressões matemáticas numa string em .NET Como executar expressões matemáticas numa string em .NET

🖩 O que é o NCalc?

O NCalc é uma biblioteca robusta para .NET que permite executar expressões definidas como strings em tempo de execução. Criada por Sébastien Ros e atualmente mantida por mim, ela oferece uma maneira poderosa e extensível de interpretar e avaliar lógica expressiva com suporte a operadores, parâmetros, lógica condicional e até funções personalizadas!

Em vez de escrever código rígido para cada regra de negócio, você pode dar ao seu sistema a capacidade de avaliar expressões dinâmicas, criadas em tempo de execução. Isso abre um leque enorme de possibilidades em engines de regras, workflows e qualquer aplicação que dependa de lógica configurável e flexível.

🧠 Arquitetura Detalhada do NCalc

A arquitetura do NCalc é dividida em três camadas essenciais: parsing, execução da expressão, e a interface de alto nível representada pela classe Expression. Cada camada possui um papel bem definido, contribuindo para a separação de responsabilidades e extensibilidade.

🔍 Parsing

O processo de parsing transforma a string da expressão em uma estrutura de dados hierárquica. O NCalc utiliza o Parlot como biblioteca responsável pelo parsing, convertendo expressões como "1 + 2 * 3" em representações internas chamadas ASTs (árvores de sintaxe abstrata).

Você também pode implementar seu próprio parser desde que ele implemente a interface ILogicalExpressionFactory, permitindo adaptar o NCalc para casos muito específicos ou DSLs internas.

🌳 O que é uma AST?

AST significa Abstract Syntax Tree (Árvore de Sintaxe Abstrata). É uma estrutura de dados que representa hierarquicamente a gramática da expressão. Em vez de trabalhar com a string bruta, a AST organiza os operadores e operandos em nós e subnós.

Por exemplo, a expressão "2 + 3 * 5" não é lida da esquerda para a direita, mas sim como uma árvore onde a multiplicação ocorre antes da soma. O nó raiz é a adição, e um dos filhos é outro nó de multiplicação. Essa organização é o que permite ao NCalc avaliar corretamente expressões complexas com regras de precedência e associatividade.

⚙️ Executação com Visitor Pattern

Com a AST pronta, o próximo passo é executar a expressão. Isso é feito com o pattern Visitor, um design pattern clássico que separa a lógica de navegação da lógica de processamento.

O visitor pattern funciona com o conceito do polimorfismo. Um visitor possui diversos métodos para cada classe diferente que pode herdar de LogicalExpression e esta, possui um método que recebe um visitor. É possível ir a mais a fundo neste conceito com este artigo do Sebastien Rós.

O NCalc inclui visitors como EvaluationVisitor e SerializationVisitor, e permite que você crie os seus próprios.

Com isso, você pode não só avaliar expressões, mas também transformá-las, otimizá-las, serializá-las ou até validá-las antes da execução.

Para criar sua própria regra de execução própria, basta implementar a interface IEvaluationVisitorFactory.

🧪 Expression: A Classe Principal

A classe Expression é a porta de entrada do NCalc. Ela cuida de toda a mágica para você: parsing, validação e avaliação. Basta instanciar com uma string e chamar Evaluate(). Também permite injeção de variáveis via dicionário e funções customizadas.

Você pode construir engines de cálculo baseadas em contexto, onde expressões são carregadas de banco de dados, arquivos de configuração ou digitadas por usuários finais. Tudo isso com segurança e controle.

A classe Expression abstrai toda lógica de AST e do Visitor Pattern do consumidor final da biblioteca.

Além disso, esta classe faz outras operações importantes, como cache da AST e detecção de erros.

💻 Exemplos

Evaluation simples:


var expression = new Expression("2 + 3 * 5");
Console.WriteLine(17 == expression.Evaluate()); //Isso vai retornar true.
    

Funções customizadas:


var expression = new Expression("SecretOperation(3, 6)");
expression.Functions["SecretOperation"] = (args) => {
    return (int)args[0].Evaluate() + (int)args[1].Evaluate();
};
Console.WriteLine(9 == expression.Evaluate()); //Esta função vai retornar 9.

🚀 Por que Executar Strings como Expressões?

Executar strings como expressões traz uma enorme vantagem: desacoplamento. Ao invés de codificar regras diretamente no C#, você pode colocá-las fora da aplicação — e mudá-las sem recompilar. Isso é ouro em sistemas que demandam agilidade e customização.

Casos de uso comuns:

📚 Recursos Adicionais

← Voltar ao ínicio