Round #514
09 May 2026, 20:06· csharp· qwen2.5-coder-7b-instruct· r13-clean-hints
- Complexity
- band 0
- ZP / UO / OBS
- 3 / 2 / 4
- Journey weight
- 624
- Lightshift ΔL
- —
Prompt
Implement a LINQ expression tree builder for dynamic filtering
Zero-point index (what the engine surfaced)
ZPI-ZPI-0023 | 2026-05-09T20:06:49Z
Implement a LINQ expression tree builder for dynamic filtering
ZERO POINT — 3 entries (structural invariants)
● hsl(7.18, 100%, 50%) class [feature]
● hsl(0.00, 100%, 50%) public [feature]
● hsl(84.10, 100%, 50%) namespace [feature]
UNOBSERVED — 2 entries (implied truths)
○ hsl(340.51, 100%, 21%) IEnumerable of T [feature]
○ hsl(15.38, 100%, 21%) var [feature]
OBSERVED — 4 entries (explicit in request)
◉ hsl(135.38, 100%, 21%) dynamic [feature]
◉ hsl(249.23, 100%, 21%) With expression [feature]
◉ hsl(264.62, 100%, 21%) is expression [feature]
◉ hsl(265.64, 100%, 21%) as expression [feature]
COMPLEXITY │ 9 entries │ spread: 325° │ band: LOW
Baseline response (no ZPI)
Creating a LINQ expression tree builder for dynamic filtering involves constructing an `Expression` that can be used to filter data at runtime. This is particularly useful when you need to apply filters based on user input or other dynamic conditions.
Below is a simple example of how you can implement a LINQ expression tree builder in C#:
```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
public class ExpressionTreeBuilder<T>
{
private readonly List<Expression> _expressions = new List<Expression>();
public ExpressionTreeBuilder()
{
}
public void AddFilter(string propertyName, object value, string operation)
{
var parameter = Expression.Parameter(typeof(T), "x");
var property = Expression.Property(parameter, propertyName);
var constant = Expression.Constant(value);
Expression filterExpression;
switch (operation.ToLower())
{
case "equals":
filterExpression = Expression.Equal(property, constant);
break;
case "not equals":
filterExpression = Expression.NotEqual(property, constant);
break;
case "greater than":
filterExpression = Expression.GreaterThan(property, constant);
break;
case "less than":
filterExpression = Expression.LessThan(property, constant);
break;
case "greater than or equal to":
filterExpression = Expression.GreaterThanOrEqual(property, constant);
break;
case "less than or equal to":
filterExpression = Expression.LessThanOrEqual(property, constant);
break;
default:
throw new ArgumentException("Invalid operation");
}
_expressions.Add(filterExpression);
}
public IQueryable<T> Build(IQueryable<T> query)
{
if (_expressions.Count == 0)
{
return query;
}
var body = _expressions.Aggregate((current, next) => Expression.AndAlso(current, next));
var lambda = Expression.Lambda<Func<T, bool>>(body, Expression.Parameter(typeof(T), "x"));
return query.Where(lambda);
}
}
// Example usage
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main()
{
var people = new List<Person>
{
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 },
new Person { Name = "Charlie", Age = 35 }
}.AsQueryable();
var builder = new ExpressionTreeBuilder<Person>();
builder.AddFilter("Name", "Alice", "equals");
builder.AddFilter("Age", 30, "greater than or equal to");
var filteredPeople = builder.Build(people);
foreach (var person in filteredPeople)
{
Console.WriteLine($"{person.Name}, {person.Age}");
}
}
}
```
### Explanation
1. **ExpressionTreeBuilder Class**:
- This class is generic and takes a type `T` which represents the entity you are filtering.
- It maintains a list of expressions that will be combined to form the final filter.
2. **AddFilter Method**:
- This method allows adding filters dynamically based on property name, value, and operation (e.g., "equals", "greater than").
- It constructs an `Expression` for each filter condition and adds it to the list.
3. **Build Method**:
- This method combines all the expressions in the list using logical AND (`Expression.AndAlso`) to form a single expression.
- It then creates a lambda expression that represents the final filter condition.
- Finally, it applies this lambda expression to the input `IQueryable<T>` using the `Where` method.
4. **Example Usage**:
- The example demonstrates how to use the `ExpressionTreeBuilder` class to dynamically build and apply filters to a list of `Person` objects.
This implementation provides a basic framework for building dynamic LINQ queries. You can extend it by adding more operations, handling different types of properties (e.g., dates, collections), and optimizing performance as needed.
Enhanced response (with ZPI)
To implement a LINQ expression tree builder for dynamic filtering, we'll create a utility that can construct `Expression<Func<T, bool>>` dynamically based on provided criteria. This approach allows us to build complex queries at runtime without hardcoding them.
Here's the implementation:
```csharp
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
public static class ExpressionTreeBuilder
{
public static Expression<Func<T, bool>> BuildFilter<T>(Dictionary<string, object> criteria)
{
if (criteria == null || criteria.Count == 0)
throw new ArgumentException("Criteria cannot be null or empty.");
var parameter = Expression.Parameter(typeof(T), "x");
var body = Expression.Constant(true);
foreach (var kvp in criteria)
{
var property = typeof(T).GetProperty(kvp.Key);
if (property == null)
throw new ArgumentException($"Property '{kvp.Key}' not found on type {typeof(T)}.");
var value = Expression.Constant(kvp.Value, property.PropertyType);
var propertyAccess = Expression.Property(parameter, property);
var equalsExpression = Expression.Equal(propertyAccess, value);
body = Expression.AndAlso(body, equalsExpression);
}
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
}
```
### Explanation
1. **Parameter and Body Initialization**:
- We start by creating a parameter expression for the type `T` named "x".
- The initial body of the lambda expression is set to `true`, which will be used as a starting point for combining conditions.
2. **Iterating Over Criteria**:
- For each key-value pair in the criteria dictionary, we retrieve the corresponding property from the type `T`.
- If the property does not exist, an exception is thrown.
- We create a constant expression for the value and access the property using `Expression.Property`.
3. **Building the Expression Tree**:
- For each criterion, we build an equality expression (`Expression.Equal`) comparing the property to the provided value.
- We then combine this equality expression with the existing body of the lambda using `Expression.AndAlso`, ensuring that all conditions must be true for the filter to return `true`.
4. **Returning the Lambda Expression**:
- Finally, we create and return a lambda expression from the parameter and combined body.
### Usage Example
Here's how you can use this utility to dynamically build a filter:
```csharp
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public static void Main()
{
var criteria = new Dictionary<string, object>
{
{ "Name", "John" },
{ "Age", 30 }
};
var filter = ExpressionTreeBuilder.BuildFilter<Person>(criteria);
var people = new List<Person>
{
new Person { Name = "John", Age = 30 },
new Person { Name = "Jane", Age = 25 },
new Person { Name = "John", Age = 28 }
};
var filteredPeople = people.Where(filter).ToList();
foreach (var person in filteredPeople)
{
Console.WriteLine($"{person.Name}, {person.Age}");
}
}
```
### Output
```
John, 30
John, 28
```
This example demonstrates how to dynamically build a filter for a list of `Person` objects based on the provided criteria. The resulting lambda expression is used to filter the list, returning only those people who match all specified conditions.
Grader chain
Each grader reads the same baseline + enhanced pair and casts an independent verdict. Disagreement is the framework's own signal — not noise to be averaged away.
V1samba/Meta-Llama-3.3-70B-Instruct
BetterV4qwen2.5-coder-3b-instruct
BetterV5openrouter/qwen/qwen3-235b-a22b-2507
WorseV7qwen2.5-coder-7b-instruct
BetterV8openai/gpt-4.1
WorseV9anthropic/claude-opus-4-7
WorseV12openai/gpt-4o
BetterComments
Our grader said what it said. What do you say? Comment as a guest below.
No comments yet. Be the first to say what you make of this round.