omy.Utils.Expressions.CSyntax
2.0.0-rc.1
This is a prerelease version of omy.Utils.Expressions.CSyntax.
dotnet add package omy.Utils.Expressions.CSyntax --version 2.0.0-rc.1
NuGet\Install-Package omy.Utils.Expressions.CSyntax -Version 2.0.0-rc.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="omy.Utils.Expressions.CSyntax" Version="2.0.0-rc.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="omy.Utils.Expressions.CSyntax" Version="2.0.0-rc.1" />
<PackageReference Include="omy.Utils.Expressions.CSyntax" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add omy.Utils.Expressions.CSyntax --version 2.0.0-rc.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: omy.Utils.Expressions.CSyntax, 2.0.0-rc.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package omy.Utils.Expressions.CSyntax@2.0.0-rc.1
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=omy.Utils.Expressions.CSyntax&version=2.0.0-rc.1&prerelease
#tool nuget:?package=omy.Utils.Expressions.CSyntax&version=2.0.0-rc.1&prerelease
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Utils.Expressions.CSyntax
Utils.Expressions.CSyntax provides a C-like expression compiler that targets LINQ expression trees (System.Linq.Expressions).
The main component is CSyntaxExpressionCompiler in the Utils.Expressions.CSyntax.Runtime namespace.
What it is for
- Compile textual expressions into .NET
Expressiontrees. - Execute dynamic expressions with a symbol context.
- Declare functions and reuse them in the same source.
- Share one context instance across multiple expression compilers.
- Persist runtime symbols (values and static callables) to/from streams.
Installation
This package's first publication is the 2.0.0-rc.1 release candidate - there is no earlier stable
version, so dotnet add package requires an explicit version (NuGet does not install a prerelease
by default):
dotnet add package omy.Utils.Expressions.CSyntax --version 2.0.0-rc.1
Examples
1) Arithmetic one-liner
using System.Linq.Expressions;
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
Expression expression = compiler.Compile("1 + 2 * 3");
var lambda = Expression.Lambda<Func<double>>(Expression.Convert(expression, typeof(double))).Compile();
double result = lambda(); // 7
2) Boolean one-liner
using System.Linq.Expressions;
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
Expression expression = compiler.Compile("3 > 1 && 4 <= 4");
var lambda = Expression.Lambda<Func<bool>>(Expression.Convert(expression, typeof(bool))).Compile();
bool result = lambda(); // true
3) Compile with symbols
using System.Linq.Expressions;
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
ParameterExpression x = Expression.Parameter(typeof(double), "x");
Expression expression = compiler.Compile("x * 2 + 1", new Dictionary<string, Expression>
{
["x"] = x,
});
var lambda = Expression.Lambda<Func<double, double>>(Expression.Convert(expression, typeof(double)), x).Compile();
double result = lambda(4); // 9
4) Compile a strongly typed lambda (one-liner)
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
Expression<Func<int, int>> expression = compiler.Compile<Func<int, int>>("(x) => x + 1");
Func<int, int> function = expression.Compile();
int result = function(41); // 42
5) Functions declared in source
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
var context = new ExpressionCompilerContext();
compiler.CompileSource(
"""
public double add(double a, double b) { a + b; }
public double twice(double x) { add(x, x); }
""",
context);
if (!context.TryGet("twice", out object? twiceSymbol) || twiceSymbol is not Func<double, double> twice)
{
throw new InvalidOperationException("Unable to resolve function 'twice'.");
}
double result = twice(5d); // 10
6) Lambda in context + invocation
using System.Linq.Expressions;
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
var context = new ExpressionCompilerContext();
context.Set("increment", (Func<double, double>)(x => x + 1));
Expression expression = compiler.Compile("increment(41)", context);
var lambda = Expression.Lambda<Func<double>>(Expression.Convert(expression, typeof(double))).Compile();
double result = lambda(); // 42
7) Standard control flow: if / else
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
var context = new ExpressionCompilerContext();
compiler.CompileSource(
"""
public double abs(double x)
{
if (x >= 0) x
else -x
}
""",
context);
if (!context.TryGet("abs", out object? absSymbol) || absSymbol is not Func<double, double> abs)
{
throw new InvalidOperationException("Unable to resolve function 'abs'.");
}
double a = abs(3); // 3
double b = abs(-3); // 3
8) Standard control flow: for
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
var context = new ExpressionCompilerContext();
compiler.CompileSource(
"""
public double sumTo(int n)
{
int i = 0;
double sum = 0;
for (i = 1; i <= n; i = i + 1) sum = sum + i;
sum
}
""",
context);
if (!context.TryGet("sumTo", out object? sumToSymbol) || sumToSymbol is not Func<int, double> sumTo)
{
throw new InvalidOperationException("Unable to resolve function 'sumTo'.");
}
double result = sumTo(4); // 10
9) Standard control flow: foreach
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
var context = new ExpressionCompilerContext();
context.Set("values", new[] { 1, 2, 3, 4 });
compiler.CompileSource(
"""
public int sumValues()
{
int sum = 0;
foreach (int item in values) sum = sum + item;
sum
}
""",
context);
if (!context.TryGet("sumValues", out object? sumValuesSymbol) || sumValuesSymbol is not Func<int> sumValues)
{
throw new InvalidOperationException("Unable to resolve function 'sumValues'.");
}
int result = sumValues(); // 10
10) Persist and restore a shared context
using Utils.Expressions;
using Utils.Expressions.CSyntax.Runtime;
var compiler = new CSyntaxExpressionCompiler();
var context = new ExpressionCompilerContext();
context.Set("add", (Func<int, int, int>)((a, b) => a + b));
compiler.CompileSource("public int twice(int x) { add(x, x); }", context);
using MemoryStream stream = new();
context.WriteToStream(stream);
stream.Position = 0;
ExpressionCompilerContext restored = ExpressionCompilerContext.ReadFromStream(stream);
Expression expression = compiler.Compile("twice(21)", restored);
int result = Expression.Lambda<Func<int>>(Expression.Convert(expression, typeof(int))).Compile()(); // 42
Notes
- The compiler accepts C-like syntax (arithmetic operations, blocks,
if,for,foreach, functions, etc.). - The final expression type depends on context and generated LINQ conversions.
- For advanced scenarios, use
ExpressionCompilerContextto register symbols, overloaded callables, and persisted runtime values. - Unused variable elimination — local variable declarations that are never read are silently removed from the compiled block. If the initializer expression has observable side effects (e.g. a method call), the initializer is kept as a standalone statement and the variable itself is dropped. Pure initializers (constants, parameter references) are discarded entirely.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- omy.Utils (= 2.0.0-rc.1)
- omy.Utils.Parser (= 2.0.0-rc.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0-rc.1 | 97 | 8/28/2026 |