Skip to main content

C# to JS: LINQ Expressions and ExpressionVisitor

How to translate (some) C# to JavaScript

If you’ve ever used something like EF Core you may have noticed that methods like LINQ’s Where take an Expression<Func<...>> as the first argument, instead of simply a Func<...>:

'Where' method definitions
Expressions were introduced in .NET 3.5 along with the rest of LINQ and they represent the code tree that a lambda is composed of. For example, if you had a lambda like () => a + b, this is how the resulting expression tree would look like:

Tree chart
.NET 4.0 later introduced ExpressionVisitor, which lets you traverse the expression tree. Take this visitor for example:

public class ConsolePrinterVisitor : ExpressionVisitor
    //This is just a helper method to get the Expression, normally you would already have it
    //so you'd just do ConsolePrinterVisitor.Visit(expression)
    public void WriteLambda(Expression<Func<object>> expression)

    protected override Expression VisitBinary(BinaryExpression node)
        Console.Write($" {GetOperationChar(node.NodeType)} ");

        return node;

    protected override Expression VisitMember(MemberExpression node)
        return node;

    private static string GetOperationChar(ExpressionType type)
        switch (type)
            case ExpressionType.Add:
                return "+";
            case ExpressionType.Subtract:
                return "-";
            //Add other operations

        return null;


int a = 1, b = 2, c = 3;

new ConsolePrinterVisitor().WriteLambda(() => a + b - c);
//Output: ((a + b) - c)

new ConsolePrinterVisitor().WriteLambda(() => a + (b - c));
//Output: (a + (b - c))

I’m sure you can already tell where JavaScript comes into all of this. By «simply» extending the visitor class to include method calls, field accesses and other language features you can successfully translate a C# lambda expression to a JS one. This is exactly what this class in my vue-aspvalidate library does in order to reuse a validator lambda in the ASP.NET Core back-end and in the JS/TS front-end! Here’s how that class is used:

Expression<Func<string, bool>> expr = o => o.Length > 4 && Regex.IsMatch(o, "^foo\\w+$", RegexOptions.Multiline | RegexOptions.IgnoreCase);

var js = expr.ToJs();

//Output: o=>o.length>4&&new RegExp("^foo\\w+$","gim").test(o)
//Beautified: o => o.length > 4 && new RegExp("^foo\\w+$", "gim").test(o)

For completeness’ sake, this is how the expression used in this example looks like in tree form:

Tree chart

Reading expressions is a powerful tool to have under your belt, but the real fun part comes with creating expression trees at runtime. This way you can dynamically generate an expression tree at runtime, compile it and run it at the exact same speed as normal, compiled code! This will come in the next post, so make sure to subscribe so you don’t miss it.


Popular posts from this blog

ConditionalWeakTable, what does it do?

C#'s ConditionalWeakTable, what does it do?C# has many lesser known features, some more useful than others, and one of them is the ConditionalWeakTable<TKey, TValue> (keep in mind that TKey and TValue must be reference types).
You can think of this type as a dictionary where the keys are weakly referenced, meaning that they won’t count when the GC checks if the object has to be collected. Additionally, when the keys do eventually get collected by the GC, that entry will get removed from the dictionary. This means that you can attach arbitrary objects to any object, allowing you to do something like this:publicstaticclassExtensions{privatestatic ConditionalWeakTable<object,dynamic> Table =newConditionalWeakTable<object,dynamic>();publicstaticdynamicData(thisobject obj){if(!Table.TryGetValue(obj,outvar dyn)) Table.Add(obj, dyn =newExpandoObject());return dyn;}}...var myObject ="hello"; myObject.Data().Foo ="bar"; Assert.AreEqual(myO…

Building LINQ Expressions: How to run dynamic code at runtime (part 1)

How to run dynamic code at runtime (part 1)In my previous post I talked about how to read LINQ expressions using an ExpressionVisitor, however reading isn’t the only thing you can do with expressions: you can build them at runtime!If you’ve ever used reflection you’re probably aware that you shouldn’t use them in performance-critical situations as they’re one of the slowest parts of .NET, but what if you desperately need to use it?Enter the world of expression-building. Before I show you how anything works, I want you to compare speeds: RawAccess: 00:00:00.0000344 b*1,0 (3,44E-06ms per iteration) ReflectionNoCache: 00:00:00.0018118 b*52,7 (0,00018118ms per iteration) ReflectionWithCache: 00:00:00.0009518 b*27,7 (9,518E-05ms per iteration) ExpressionNoCache: 00:00:00.9333534 b*27132,4 (0,09333534ms per iteration) ExpressionWithCache: 00:00:00.0000424 b*1,2 (4,24E-06ms per iteration) Benchmark ran with .NET Core 2.2 on an AMD Ryzen 2400G @ 3.85Ghz and Windows 10.As you can …