Dynamic Code Execution in .NET with C# Eval Expression
Learn how to run C# code at runtime using the C# Eval Expression library with simple Execute and Compile examples for beginners.
Imagine you run a small sweet shop. You have a printed price list, and every time the price of laddu changes, you must print a brand new list. That is slow and wastes paper. Now imagine a small chalkboard next to the till. When a price changes, you just rub out the old number and write the new one. The shop keeps working. No reprinting. No closing for the day.
Most C# code is like the printed price list. You write it, you build it, and you ship it. To change anything, you build and ship again. But sometimes you want a chalkboard instead, a place where a rule can change while the program is still running. That is what dynamic code execution gives you. And the C# Eval Expression library is one of the friendliest ways to do it in .NET.
In this guide you will learn what dynamic code execution means, when it helps, and how to use the two main tools the library gives you: Eval.Execute and Eval.Compile. We will keep things simple and gentle, with plenty of small examples.
What does "dynamic code execution" mean?
Normally, C# code is turned into a runnable program before it runs. This happens at compile time, on your machine or a build server. Once the program starts, the code is fixed.
Dynamic code execution flips this around. You hand the program a piece of code written as a plain string, and the program turns that string into something it can run, right now, while it is already running. This moment is called runtime.
Here is the difference in one picture.
The key idea: with a normal program, the rule lives in the source file. With dynamic code, the rule can live in a database, a config file, or even a text box, and you can change it without rebuilding.
Meet the C# Eval Expression library
The C# Eval Expression library (its NuGet package is named Z.Expressions.Eval) is built by ZZZ Projects. It lets you evaluate, compile, and run C# code and expressions at runtime. It understands a huge slice of normal C#: math, strings, booleans, LINQ, lambdas, your own classes, and more.
To start, you add the package to your project.
// In your terminal, inside the project folder:
// dotnet add package Z.Expressions.Eval
using Z.Expressions; // This namespace gives you Eval.Execute and Eval.CompileOne important note for honesty: the library is free up to 50 characters for both the Execute and Compile methods. That is enough to learn and to run small expressions. Longer expressions need a paid license. Always check the current pricing before you ship something big.
Your first evaluation with Eval.Execute
The simplest tool is Eval.Execute. You give it a string of C# code, and it runs that code and gives you back the answer.
using Z.Expressions;
// Run a tiny math expression written as a string
int result = Eval.Execute<int>("1 + 2");
Console.WriteLine(result); // 3Notice the <int> part. That tells the library "the answer will be an int, please give it back to me as an int." This is called the generic variant. There is also a plain version, Eval.Execute("1 + 2"), that returns an object, but using the typed version is clearer and safer.
The string "1 + 2" is not special to C# when your program is built. It is just text. The library reads that text at runtime and figures out what it means. That is the magic.
Passing values into your expression
A fixed sum like "1 + 2" is not very useful. The real power shows up when you pass in values. The library lets you hand over an object, and then your expression can use the names of that object's members.
using Z.Expressions;
// X and Y come from an anonymous object
int result = Eval.Execute<int>("X + Y", new { X = 1, Y = 2 });
Console.WriteLine(result); // 3Here we passed new { X = 1, Y = 2 }. The library automatically registers the names X and Y, so the expression "X + Y" knows what they mean. You can pass many kinds of value holders.
| Way to pass values | Example | Good for |
|---|---|---|
| Anonymous object | new { X = 1, Y = 2 } | Quick, simple cases |
| Your own class | new Order { Total = 500 } | Real business objects |
| Dictionary | new Dictionary<string, object> | Names known only at runtime |
| ExpandoObject | dynamic bag of values | Flexible, loose data |
This flexibility is what makes the library feel friendly. You do not have to twist your data into a special shape. You pass what you already have.
How Eval.Execute handles your call
Steps
String
Your C# code as text
Values
An object with named members
Parse
Library reads the code
Run
Code executes at runtime
Answer
Typed result returns to you
A slightly bigger example with LINQ
The library is not limited to small sums. It understands LINQ, lambdas, and collections too. Here is a filter that keeps only the numbers in a range.
using Z.Expressions;
var result = Eval.Execute<List<int>>(
"new List<int> { 1, 2, 3, 4, 5 }.Where(x => x > MinValue && x < MaxValue).ToList()",
new { MinValue = 1, MaxValue = 5 }
);
// result holds 2, 3, 4
Console.WriteLine(string.Join(", ", result));Read that slowly. The whole LINQ query lives inside a string. The MinValue and MaxValue come from the object we passed. The library runs the lambda x => x > MinValue && x < MaxValue for each number. This is the same C# you already know, just written as text and run later.
When running once is wasteful: meet Eval.Compile
Eval.Execute does a lot of work each time you call it. It reads the string, understands it, and runs it. If you only do this once, that is fine. But what if you must run the same expression thousands of times with different inputs? Reading the string every single time would be slow.
This is where Eval.Compile shines. It reads the string once and gives you back a ready-to-use function, called a delegate. After that, you call the delegate directly, with no re-reading. The official docs note this can be up to 1000x quicker than calling Execute over and over.
using Z.Expressions;
// Compile once: build a Func that takes an int and returns a string
var compiled = Eval.Compile<Func<int, string>>(
"i % 15 == 0 ? i + \" => FizzBuzz\" : i.ToString()",
"i"
);
// Call the delegate many times, fast
for (int i = 1; i <= 5; i++)
{
Console.WriteLine(compiled(i));
}The "i" at the end names the parameter, so the expression knows that i is the incoming number. The result type Func<int, string> says "this takes an int and gives back a string." Once you hold compiled, calling it is just like calling any normal method.
Here is the difference in cost between the two approaches.
Execute vs Compile: which should you pick?
A simple rule helps you choose.
| Question | Use Execute | Use Compile |
|---|---|---|
| How often do you run it? | Once | Many times |
| Does the expression change often? | Yes | No, it is stable |
| Do you need top speed in a loop? | No | Yes |
| Is the code simple and short? | Often | Sometimes |
Think of Execute like cooking one cup of tea for a guest. You do it, you serve it, done. Think of Compile like setting up a tea stall: you do the setup once, then serve hundreds of cups quickly. If a rule will run again and again, compile it first.
Choosing Execute or Compile
Steps
Start
You have an expression
Run once?
Will it run a single time?
Execute
Yes: keep it simple
Compile
No: build a delegate and reuse
Real-life uses
Why would you ever want this? Here are everyday reasons that show up in real apps.
- Email templates with placeholders. A marketing team writes
Hello FirstName, your order Total is ready. The values fill in at runtime. No code change needed for new templates. - Dynamic filters for Entity Framework. A user builds a search with chosen fields. You turn their choices into a filter expression at runtime.
- Business rules that change often. Discount rules, tax rules, or bonus points can live in a database. Business folks tweak them without waiting for a new release.
- Spreadsheet-style formulas. Let users type a formula like
Price * Quantity * 0.9and compute the result.
The thread tying these together is the same: the rule is not known when you build the app. It is decided later, by data or by a person.
A short safety talk (please read this)
Running code from a string is powerful, and power needs care. If the string comes from a user you do not trust, they could try to run code that hurts your system. This is a real risk, not a small one.
Keep these habits.
- Only run code you trust. Code written by your own team or stored safely is fine.
- Never paste raw user input straight into
Execute. If users must supply formulas, keep the allowed shapes tight and simple. - Treat dynamic code like an open door. Lock it unless you have a good reason to leave it open.
Handling errors gracefully
When the code in your string is wrong, the library throws an exception, just like a normal compile error would, but at runtime. Wrap risky calls in a try/catch so one bad expression does not crash your whole app.
using Z.Expressions;
try
{
// This expression has a mistake on purpose
var value = Eval.Execute<int>("X + ");
Console.WriteLine(value);
}
catch (Exception ex)
{
// Tell the user kindly instead of crashing
Console.WriteLine("That formula could not run: " + ex.Message);
}This matters most when the expression comes from outside your code, such as a config file someone edited by hand. A small typo should give a friendly message, not a broken page.
Tips for using it well
A few small habits make this library pleasant to work with over time.
- Name your parameters clearly.
TotalandQuantityread better thanaandbinside an expression string. - Compile and store delegates you reuse. Keep them in a field or a cache so you build each one only once.
- Keep expressions short. Remember the free limit is 50 characters. Short expressions are also easier to read and test.
- Log what you run. When a dynamic rule misbehaves, a log of the exact expression saves hours of guessing.
Putting it all together
Let us end with one tiny scene. Suppose your shop gives a discount that changes during festivals. Instead of editing code each time, you store the rule as text.
using Z.Expressions;
// This rule could come from a database row
string discountRule = "Price - (Price * Percent / 100)";
// Compile once because we will use it for every customer today
var applyDiscount = Eval.Compile<Func<decimal, decimal, decimal>>(
discountRule,
"Price", "Percent"
);
decimal finalPrice = applyDiscount(500m, 10m);
Console.WriteLine(finalPrice); // 450When the festival ends, you change one row in the database. The shop keeps running. That is the chalkboard, not the printed price list.
References and further reading
- C# Eval Expression official site — home page with overview and pricing.
- Eval-Expression.NET on GitHub — source code and issues.
- Eval.Execute documentation — all the overloads and parameter options.
- Eval.Compile documentation — how to build and reuse delegates.
- Get started with your first evaluation — a gentle hands-on intro.
- Z.Expressions.Eval on NuGet — the package to install.
Quick recap
- Dynamic code execution means running C# written as a string while your program is already running.
- The C# Eval Expression library (
Z.Expressions.Eval) makes this easy and understands math, strings, LINQ, and your own classes. Eval.Executeruns an expression once. Pass values with an anonymous object, a class, a dictionary, or an ExpandoObject.Eval.Compilereads an expression once and returns a fast delegate, ideal when you run the same rule many times.- Pick Execute for one-off runs and Compile for repeated runs in loops.
- The library is free up to 50 characters; longer expressions need a license.
- Be careful with untrusted input and wrap calls in
try/catchso a bad formula never crashes your app.
Related Posts
How to Write Elegant Code with C# Pattern Matching
Learn C# pattern matching the easy way. Use is, switch expressions, property and list patterns to write clean, readable, and elegant .NET code.
How to Apply Functional Programming in C#: A Beginner's Guide
Learn functional programming in C# the simple way: pure functions, immutability, records, LINQ, pattern matching, and composition with friendly examples.
New Features in C# 13: A Friendly Beginner's Guide
Learn the new features in C# 13 with simple words, real-life examples, diagrams, and code you can read in minutes. Great for beginners.
Mastering Exception Handling in C#: A Comprehensive Guide
Learn C# exception handling the friendly way: try, catch, finally, custom exceptions, filters, throw vs throw ex, and real best practices for .NET 10.
Getting Started with C# Records: A Beginner's Friendly Guide
Learn C# records the easy way: value equality, with expressions, positional syntax, and record struct, explained with simple real-life examples.
Why I Switched to Primary Constructors for DI in C#
A friendly guide on why primary constructors made my C# dependency injection cleaner, with simple examples, diagrams, tables, and honest trade-offs.