Best and shortest way to evaluate mathematical expressions - c#

There are many algorithms to evaluate expressions, for example:
By Recursive Descent
Shunting-yard algorithm
Reverse Polish notation
Is there any way to evaluate any mathematical expression using C# .net reflection or other modern .net technology?

Further to Thomas's answer, it's actually possible to access the (deprecated) JScript libraries directly from C#, which means you can use the equivalent of JScript's eval function.
using Microsoft.JScript; // needs a reference to Microsoft.JScript.dll
using Microsoft.JScript.Vsa; // needs a reference to Microsoft.Vsa.dll
// ...
string expr = "7 + (5 * 4)";
Console.WriteLine(JScriptEval(expr)); // displays 27
// ...
public static double JScriptEval(string expr)
{
// error checking etc removed for brevity
return double.Parse(Eval.JScriptEvaluate(expr, _engine).ToString());
}
private static readonly VsaEngine _engine = VsaEngine.CreateEngine();

It's certainly possible. The CodeSnippetCompileUnit class does basically this.
I wrote you some example usage code. You'll need to include these namespaces:
System.CodeDom.Compiler;
System.CodeDom;
Microsoft.CSharp;
System.Reflection;
Here's the code:
string source = #"
class MyType
{
public static int Evaluate(<!parameters!>)
{
return <!expression!>;
}
}
";
string parameters = "int a, int b, int c";
string expression = "a + b * c";
string finalSource = source.Replace("<!parameters!>", parameters).Replace("<!expression!>", expression);
CodeSnippetCompileUnit compileUnit = new CodeSnippetCompileUnit(finalSource);
CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
CompilerResults results = provider.CompileAssemblyFromDom(parameters, compileUnit);
Type type = results.CompiledAssembly.GetType("MyType");
MethodInfo method = type.GetMethod("Evaluate");
// The first parameter is the instance to invoke the method on. Because our Evaluate method is static, we pass null.
int result = (int)method.Invoke(null, new object[] { 4, -3, 2 });
Replace 'parameters' and 'expression' by whatever, and you've got yourself a general expression evaluator.
If you get a FileNotFoundException in results.CompiledAssembly, then the snippet failed to compile.
You might also want to take a look at the System.CodeDom.CodeSnippetExpression class. It's used for more specifically reading expressions, but an expression by itself can't be compiled, so you would need to use more CodeDom to build a working class and method around it. This is useful if you want to be able to programmatically manipulate what kind of class you're generating. CodeSnippetCompileUnit is nice to generate an entire working class at once (and simpler for an example) but to manipulate it you would have to do inconvenient string manipulations.

Although using compiler services is a simple and efficient solution, it raises serious security issues if the expression is entered by a user, because it could execute virtually anything.
There's another very simple solution that is much more secure : take advantage of the JScript Eval function. You just need to follow these steps :
Create a js file named JsMath.js :
class JsMath
{
static function Eval(expression : String) : double
{
return eval(expression);
};
}
Compile it into a class library :
jsc /t:library JsMath.js
Reference the JsMath library in your C# project, and use it like that :
double result = JsMath.Eval(expression);

For me Vici.Parser works extremely well: check it out here , it's the most flexible expression parser I've found so far.
(we've used it to set up 'human-readable' business rules, with data provided by an SQL server database)
Examples are available and there's a very good support by the developer (check the website's forum).

ncalc is the best. you can find it in codeplex also in nugget.
NCalc is a mathematical expressions evaluator in .NET. NCalc can parse any expression and evaluate the result, including static or dynamic parameters and custom functions.

I think this is the best way of all. Petar Repac's answer is amazing.
Using the 'expression' argument of the DataColumn object solves incredibly and easily the topic:
static double Evaluate(string expression)
{
var loDataTable = new DataTable();
var loDataColumn = new DataColumn("Eval", typeof(double), expression);
loDataTable.Columns.Add(loDataColumn);
loDataTable.Rows.Add(0);
return (double)(loDataTable.Rows[0]["Eval"]);
}

You can use Math-Expression-Evaluator library which implements Shunting Yard algorithm that I am author of. It supports simple expressions such as 2.5+5.9, 17.89-2.47+7.16, 5/2/2+1.5*3+4.58, expressions with parentheses (((9-6/2)*2-4)/2-6-1)/(2+24/(2+4)) and expressions with variables:
var a = 6;
var b = 4.32m;
var c = 24.15m;
var engine = new ExpressionEvaluator();
engine.Evaluate("(((9-a/2)*2-b)/2-a-1)/(2+c/(2+4))", new { a, b, c});
You can also pass parameters as named variables:
dynamic dynamicEngine = new ExpressionEvaluator();
var a = 6;
var b = 4.5m;
var c = 2.6m;
dynamicEngine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6);
It supports .Net Standard 2.0 so can be used from .Net Core as well as .Net Full Framework projects and it doesn't have any external dependencies.

To dynamically compile code using the new Roslyn API's, and load the assembly in a .net core project;
string finalSource = ...;
IEnumerable<Assembly> references = ...;
var compilation = CSharpCompilation.Create("Dynamic",
new[] {
SyntaxFactory.ParseSyntaxTree(
finalSource,
CSharpParseOptions.Default
.WithLanguageVersion(LanguageVersion.Latest)
) },
references.Select(a => MetadataReference.CreateFromFile(a.Location)),
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
);
using var ms = new MemoryStream();
var e = compilation.Emit(ms);
if (!e.Success)
throw new Exception("Compilation failed");
ms.Seek(0, SeekOrigin.Begin);
var context = new AssemblyLoadContext(null, true);
var assembly = context.LoadFromStream(ms);
Note that along with any other types required by the source you are compiling. In order to load the compiled assembly within the same process, references will need to include;
AppDomain.CurrentDomain.GetAssemblies().Where(a => a.GetName().Name == "netstandard").Single(),
typeof(object).Assembly

Related

How to access anonymous fields in a dynamic assembly?

.net Framework 4.7.2...
Compiled expressions can access private fields. When I use exactly the same expression and write it to a dynamic assembly, using CompileToMethod, I get a System.FieldAccessException while trying to read the private field.
Is there anything I can do to allow the dynamic assembly to have the same access privileges that a compiled expression does? There is ancient lore that says you cannot. But I can't find anything resembling a primary source for that claim. I can't believe there is not some form of assembly attributes or permissioning that would allow access.
Can I do it if I save the assembly instead? (Writing cached marshalling assemblies to disk is a likely feature in the future).
The application is marshalling of structs to streams in a domain-specific computer music language. Serialization is not an option (another example of dynamic code in dynamic assemblies that violates access).
Example code:
The lambda expression successfully reads the value of the private field of ComplexStruct (given below). If the same expression is emitted to a dynamic assembly using CompileToMethod, it fails with an access exception.
ComplexStruct s = new ComplexStruct();
s.String1 = "abc";
// Pick a private field (one of the backing fields for a property)
FieldInfo fieldInfo = typeof(ComplexStruct).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)[0];
var structArgument = Expression.Parameter(typeof(ComplexStruct));
var lambda = Expression.Lambda<Func<ComplexStruct,String>>(
Expression.Field(structArgument, fieldInfo), // return the value of the private field.
structArgument);
Func<ComplexStruct,String> fn = lambda.Compile();
String result = fn(s);
Assert.AreEqual(structArgument.String1, result);
A struct with private fields:
// (Complex compared to simple struct where all fields
// are public or the struct is unmanaged in case you were wondering)
public struct ComplexStruct : IEquatable<ComplexStruct>
{
public String String1 { get; set; } // the backing field for this property gets read.
public String String2 { get; set; }
public String String3 { get; }
public ComplexStruct(String v1, String v2)
{
String1 = v1;
String2 = v2;
}
public bool Equals(ComplexStruct other)
{
return String1 == other.String1 && String2 == other.String2;
}
}
Creation of the assembly:
AppDomain myAppDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "DynamicAssembly";
this.saveAssembly = ServiceBase.DEBUG;
assemblyBuilder = myAppDomain.DefineDynamicAssembly(
myAsmName,
saveAssembly? AssemblyBuilderAccess.RunAndSave: AssemblyBuilderAccess.RunAndCollect);
After reviewing .net sources it seems pretty certain that there is no way for an Assembly to bypass field access checks.
thehennyy pointed out the backdoor that Linq Expressions use. DynamicMethod constructors provides a skipVisibility parameter which allows generation of IL that can access non-public fields and methods. But there's no way to integrate DynamicMethods with Dynamic Assemblies, or emit them to a saved assembly.
Given the limitations of DynamicMethods, there doesn't seem to be any reason to prefer them over Linq Expressions, given that Linq Expression APIs are infinitely easier to use that IL.Emit APIs.
In the end, I used call-outs to templated classes that generate struct serialization delegates produced by Linq Expressions in static constructors.
If you're following the same path, you may want to look at "unmanaged" structs, introduced in C# 7.2, which allow optimized serialization of structs composed entirely of ValueType members. Given that Strings are reference classes, that usually has limited value. But given that I'm trying to write allocation-free serializers, they were useful for my purposes.
See my answer to this question on more details on the undocumented IgnoreAccessCheckToAttribute which is doing what you probably want.
Here is sample code:
One legitimate use is when compiling dynamically assemblies that needs access to internal classes, as in the following code:
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(name),
AssemblyBuilderAccess.RunAndCollect);
var assmemblyNames = typesToAccess.Where(t => t is not null)
.Select(t => t!.Assembly.FullName.Split(',').First()) // Extract the name from fullName
.Distinct().ToList();
var ignoreAccessCtor = typeof(IgnoresAccessChecksToAttribute)
.GetConstructor(new Type[] { typeof(string) });
foreach (var refName in assemblyNames)
{
var builder = new CustomAttributeBuilder(ignoreAccessCtor, new object[] { refName });
assemblyBuilder.SetCustomAttribute(builder);
}

When compiling C# expression trees into methods, is it possible to access "this"?

I am trying to dynamically generate a class that implements a given interface. Because of this, I need to implement some methods. I would like to avoid directly emitting IL instructions, so I am trying to use Expression trees and CompileToMethod. Unfortunately, some of these methods need to access a field of the generated class (as if I wrote this.field into the method I am implementing). Is it possible to access "this" using expression trees? (By "this" I mean the object the method will be called on.)
If yes, what would a method like this look like with expression trees?
int SomeMethod() {
return this.field.SomeOtherMethod();
}
Expression.Constant or ParameterExpression are your friends; examples:
var obj = Expression.Constant(this);
var field = Expression.PropertyOrField(obj, "field");
var call = Expression.Call(field, field.Type.GetMethod("SomeOtherMethod"));
var lambda = Expression.Lambda<Func<int>>(call);
or:
var obj = Expression.Parameter(typeof(SomeType));
var field = Expression.PropertyOrField(obj, "field");
var call = Expression.Call(field, field.Type.GetMethod("SomeOtherMethod"));
var lambda = Expression.Lambda<Func<SomeType, int>>(call, obj);
(in the latter case, you'd pass this in as a parameter, but it means you can store the lambda and re-use it for different target instance objects)
Another option here might be dynamic if your names are fixed:
dynamic obj = someDuckTypedObject;
int i = obj.field.SomeOtherMethod();

c# FsCheck cannot convert lambda expression

I'm trying to get a C# FsCheck generator to generate a series
of commands which are initialized with random strings. I came up with
the following solution:
public Gen<Command<A,B>> Next(B value)
{
var gen1 = Arb.Default.String().Generator;
var gen2 = Gen.two(gen1);
var gen3 = gen2.select((Command<A,B>)(s => new DerivedCommand(s.Item1,s.Item2)))
//DerivedCommand extends Command<A,B>
return Gen.OneOf(gen3);
}
However, VS cannot build this code:
Cannot convert lambda expression to type Command<A,B> because it is not a delegate type
I have searched solutions for this error message, but nothing I found helped.
I am using System.Linq and System.Data.Entity. Any suggestions for resolving this issue are much appreciated.
You're trying to cast (s => new DerivedCommand(s.Item1,s.Item2)), which is a lambda expression, to (Command<A,B>), which (I assume) is a class.
You probably need something like:
var gen3 = gen2.select(s => (Command<A,B>)(new DerivedCommand(s.Item1,s.Item2)));

Does the LINQ Expression API offer no way to create a variable?

I want to validate my assumption that the LINQ Expression API does not have any means for us to create an expression that represents the creation of a local variable.
In other words, you cannot create an expression to represent:
int local;
since that is a variable declaration statement, and the API does not support statement lambdas. The only state that a lambda expression, as represented by the LINQ Expression API (and not a delegate instance) can work with is parameters it receives and the captured variables it receives via a closure.
Is my assumption (based on a few months of practice of the LINQ Expression API) correct?
False. There are some overloads of Expression.Block to do it.
What is true is that you can't create a lambda expression through the use of the C# compiler that has a variable, but that is a limitation of the compiler.
So you can't
Expression<Func<int>> exp = () => {
int v = 1;
return v;
};
but you can
var variable = Expression.Variable(typeof(int));
var lambda = Expression.Lambda<Func<int>>(
Expression.Block(
new[] { variable },
Expression.Assign(variable, Expression.Constant(1)),
variable)); // With lambda expressions, there is an implicit
// return of the last value "loaded" on the stack
since that is a variable declaration statement, and the API does not support statement lambdas.
This was true in .NET < 4.0 . In .NET 4.0 Microsoft added Expression methods to build nearly everything that can be present in the body of a method (there are some missing "things", like unsafe code keywords/operators, plus there are the primitives but there aren't complex constructs like the for or lock, that can be built on top of other constructs). Note that 90% of those added things are incompatible with LINQ-to-SQL/EF.
Well, you can use Expression.Block to declare a block which contains local variables...
For example:
using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
var x = Expression.Variable(typeof(int), "x");
var assignment1 = Expression.Assign(x, Expression.Constant(1, typeof(int)));
var assignment2 = Expression.Assign(x, Expression.Constant(2, typeof(int)));
var block = Expression.Block(new[] { x }, new[] { assignment1, assignment2 });
}
}
That builds an expression tree equivalent to:
{
int x;
x = 1;
x = 2;
}
The C# compiler doesn't use this functionality within lambda expression conversions to expression trees, which are currently still restricted to expression lambdas, as far as I'm aware.

Evaluating a mathematical expression

Guys I am up with evaluating a string mathematical expression.
First I imported the library
using System.Linq.Expressions;
Then in my codes I did,
Expression e = new Expression("(450*5)+((3.14*7)/50)*100");
double result = e.Evaluate();
however I get the error as
Cannot create an instance of the abstract class or interface 'System.Linq.Expressions.Expression'
Why the above is not working?
How can I evaluate this ?
In order to evaluate expressions like this in c#, you have to use Roslyn. Here's an example (I changed a piece of code take from here http://blogs.msdn.com/b/csharpfaq/archive/2011/12/02/introduction-to-the-roslyn-scripting-api.aspx):
using Roslyn.Scripting.CSharp;
namespace RoslynScriptingDemo {
class Program {
static void Main(string[] args) {
var engine = new ScriptEngine();
engine.Execute(#"System.Console.WriteLine((450*5)+((3.14*7)/50)*100);");
}
}
}
Expressions only let you to create a syntax tree from code:
Expression<Func<int,int,int>> add = (x, y) => x + y;
var res = add.Compilie()(2,3);
So you can't use string as a source for expression, you have to write it as a valid c# code.
I went for Ncalc.
I am posting my codes for future users who will be on same problems like me.
1.Download the Ncalc(Binaries)http://ncalc.codeplex.com/releases/view/73656
Reference the dll in your solution.(Right click > add reference > Browse > NCalc.dll)
In codes
Using NCalc;
3.May be used as
public Double Calculate(string argExpression)
{
//get the user passed string
string ExpressionToEvaluate = argExpression;
//pass string in the evaluation object declaration.
Expression z = new Expression(ExpressionToEvaluate);
//command to evaluate the value of the **************string expression
var result = z.Evaluate();
Double results = Convert.ToDouble(result.ToString());
return results;
}
Try to use NCalc:
Expression e = new Expression("(450*5)+((3.14*7)/50)*100");
double result = e.Evaluate();
http://ncalc.codeplex.com/
You can use Mathos Parser. It is a simple .NET Mathematical Expression parser.

Categories