Cel.Compiled
0.0.6
dotnet add package Cel.Compiled --version 0.0.6
NuGet\Install-Package Cel.Compiled -Version 0.0.6
<PackageReference Include="Cel.Compiled" Version="0.0.6" />
<PackageVersion Include="Cel.Compiled" Version="0.0.6" />
<PackageReference Include="Cel.Compiled" />
paket add Cel.Compiled --version 0.0.6
#r "nuget: Cel.Compiled, 0.0.6"
#:package Cel.Compiled@0.0.6
#addin nuget:?package=Cel.Compiled&version=0.0.6
#tool nuget:?package=Cel.Compiled&version=0.0.6
Cel.Compiled
Cel.Compiled is a high-performance .NET implementation of the Common Expression Language (CEL). It compiles CEL source text into optimized, reusable CelProgram<TContext, TResult> objects, making it ideal for high-frequency evaluation in rule engines, policy enforcement, and dynamic filtering.
It is designed for scenarios where expressions are compiled once and evaluated many times.
Key Features
- High Performance: Compiles to reusable programs with an unrestricted delegate helper for near-native execution speed.
- Modern .NET: Built for .NET 10+ with optimized memory usage.
- Broad Input Support: Bind to POCOs,
JsonElement,JsonNode, or custom type descriptors. - Spec-Compliant: Comprehensive support for CEL operators, functions, macros, and optional types.
- Extensible: Easily register custom functions and receiver-style extensions.
Installation
Install via NuGet:
dotnet add package Cel.Compiled
When To Use It
Cel.Compiled is a strong fit when you:
- evaluate the same expression repeatedly against many inputs
- need CEL support over POCOs,
JsonElement,JsonNode, or descriptor-backed CLR types - want custom functions or curated extension bundles without leaving .NET
If your workload is mostly one-off parse-and-run calls, an interpretive library may have lower setup cost. Cel.Compiled is optimized for warm execution.
Basic Usage
using Cel.Compiled;
// 1. Define a context (POCO or JSON)
var context = new { User = new { Age = 25, Status = "active" } };
// 2. Compile once
var program = CelExpression.Compile<dynamic, bool>("User.Age >= 18 && User.Status == 'active'");
// 3. Evaluate many times
bool isAllowed = program.Invoke(context);
Using JSON Inputs
using System.Text.Json;
var json = JsonDocument.Parse("""{"age": 25, "status": "active"}""").RootElement;
var program = CelExpression.Compile<JsonElement, bool>("age >= 18 && status == 'active'");
bool result = program.Invoke(json);
Compile Options
Custom functions, extension bundles, and type descriptors are configured through CelCompileOptions.
using Cel.Compiled;
using Cel.Compiled.Compiler;
var registry = new CelFunctionRegistryBuilder()
.AddStandardExtensions()
.Build();
var options = new CelCompileOptions
{
FunctionRegistry = registry
};
var program = CelExpression.Compile<JsonElement, bool>(
"name.trim().lowerAscii() == 'alice'",
options);
Runtime Safety For Untrusted Inputs
Use Invoke(context, runtimeOptions) when evaluating untrusted or multi-tenant expressions.
var program = CelExpression.Compile<JsonElement, bool>("items.all(x, x > 0)");
var allowed = program.Invoke(
json,
new CelRuntimeOptions
{
MaxWork = 10_000,
MaxComprehensionDepth = 4,
Timeout = TimeSpan.FromMilliseconds(100),
RegexTimeout = TimeSpan.FromMilliseconds(25)
});
MaxWork is intentionally narrow. It counts compiler-owned repeated-work checkpoints such as comprehensions and regex-backed operations, not every AST node or every CPU instruction.
Performance
Cel.Compiled is designed for runtime speed. By compiling to delegates and minimizing allocations during evaluation, it substantially outperforms the other .NET CEL libraries in steady-state runtime benchmarks.
Fresh benchmark run on 2026-03-20 from Cel.Compiled.Benchmarks/Program.cs, using the CelNetComparisonBenchmarks suite on:
- .NET SDK
10.0.104 - .NET runtime
10.0.4 - AMD Ryzen 9 7900X
Comparison workload:
1 + 2 * 3 == 7'hello world'.contains('world')[1, 2, 3].exists(x, x == 2)
Steady-state warm execution after compilation:
| Library | Mean | Relative to Cel.Compiled |
Allocated |
|---|---|---|---|
| Native C# | 7.30 ns |
1.3x faster |
0 B |
Cel.Compiled |
9.39 ns |
1.0x |
0 B |
Cel.NET |
405.71 ns |
43.2x slower |
1360 B |
Telus CEL |
3.03 us |
322.7x slower |
8808 B |
Build-and-run from scratch for the same three expressions:
| Library | Mean | Relative to Cel.Compiled |
Allocated |
|---|---|---|---|
Cel.Compiled |
678.73 us |
1.0x |
50,089 B |
Cel.NET |
1.10 ms |
1.6x slower |
3,398,264 B |
Telus CEL |
35.57 us |
19.1x faster |
124,528 B |
The important tradeoff is straightforward: Cel.Compiled stays close to native C# on the hot path, but it still pays an upfront compile cost for that speed. On this benchmark it remains far ahead of Cel.NET during warm execution, while Telus CEL has the fastest build-and-run path among the compared CEL libraries.
To reproduce the comparison:
dotnet run -c Release --project Cel.Compiled.Benchmarks -- --filter "*CelNetComparisonBenchmarks*"
BenchmarkDotNet writes detailed reports to BenchmarkDotNet.Artifacts/results/.
Supported Features
- Arithmetic:
+,-,*,/,% - Equality & Ordering:
==,!=,<,<=,>,>= - Logical:
&&,||,! - Conditionals:
cond ? a : b - Collections:
list,map,inoperator, indexing - Macros:
all,exists,exists_one,map,filter - Optional safe-navigation:
obj.?field,list[?index],map[?key] - Standard Extensions: String, Math, List, Set, Base64, and Regex extension bundles
Major Differences And Current Gaps
Cel.Compiled aims to be a practical, high-performance .NET CEL runtime, not a line-for-line clone of cel-go. The biggest current differences are:
- No dedicated static checking phase:
cel-gohas an explicit parse → check → eval pipeline with a checked AST and richer type metadata.Cel.Compileddoes perform compile-time binding and overload validation, but it does not currently expose a separateEnv.Check()-style phase. - Lighter environment model: variables are primarily inferred from
TContext, with functions and types supplied throughCelCompileOptions. There is not yet a single first-class environment object that declaratively models variables, constants, functions, types, and checker inputs together. - Runtime-first design: the library is strongest when you compile once and reuse delegates. It is less optimized for one-off evaluation or tooling workflows built around checked AST inspection.
- No portable compiled-expression serialization: compiled delegates are cached in-process, but there is no
cel-go-style serialized checked-expression or compiled-plan format that can be saved and reloaded across processes. - Partial evaluation and residualization are not implemented: unknown propagation, residual AST generation, and richer evaluation-state tooling are still gaps.
- Some
cel-goextension/library areas remain incomplete: the shipped string, list, set, base64, and regex bundles cover the common surface, but math bitwise helpers and a few advanced areas still remain. - Optional support is intentionally scoped: the core optional navigation and helper subset is implemented, but optional aggregate literal entries and broader helper parity are still narrower than
cel-go. - Regex behavior is platform-based rather than exact RE2 parity: the runtime uses the .NET regex engine and documents CEL-facing behavior, but it does not aim for byte-for-byte RE2 compatibility.
- Runtime safety controls exist but are intentionally narrow:
CelRuntimeOptionsprovides cancellation, timeout, regex timeout, work limits, and comprehension-depth limits, butMaxWorkis a practical checkpoint-based budget rather than full instruction-level metering.
Some of these may be addressed in the future but the focus is on providing a fast, reliable CEL runtime for .NET.
More Details
- Supported surface area and examples: docs/cel-support.md
- Feature research and gap analysis: docs/cel_features_research.md
License
Cel.Compiled is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.