The critical feature is a limited ability to use code as data.
We all know that, in Kotlin, when you call a method that takes an instance of a Java functional interface, you can specify the parameter with a lambda expression. Kotlin will compile it into code that produces an instance of that interface, which the method can then call.
C# has an extra feature along similar lines. When you call a method that takes an
Expression<...>, you can specify it with a lambda expression, and the compiler will compile it into code that produces an instance of the
Expression object can be called like a function, and that is how it would be used if you use an
Expression to filter a list.
Expression object is also an abstract syntax tree. This provides the receiver of the expression with an easy way to inspect the actual code that you provided in the lambda expression, and translate it into a different language, like SQL. That is how it’s used when you use an expression to filter in a database.