views:

61

answers:

3

Given this code:

        int min = 0;

        Expression<Func<List<IUser>, bool>> ulContainsJohn = 
                    (l => l.Where(u => u.FirstName == "John").Count() > min);

        Assert.AreEqual(true, ulContainsJohn.Compile()(userList));

        min = 3;

        Assert.AreEqual(true, ulContainsJohn.Compile()(userList));

The list contains 1 "John", yet the second assert fails. How do I bind the value of min to the Func eagerly, so it doesn't try to re-evaluate the variable min?

Clarification: I don't want to change the signature. I want the expression tree to avaluate min not as a variable, but as a constant expression. Is there anyway to convert the evaluation of min so that the tree has a constant expression instead of a variable evaluation?

A: 

The simplest solution is to make a separate variable:

    int min = 0;
    int staticMin = min;
    Func<List<IUser>, bool> ulContainsJohn = 
                l => l.Where(u => u.FirstName == "John").Count() > staticMin ;
SLaks
Please see the clarification I added...
Shlomo
+1  A: 

You would have to make it a parameter.

    Expression<Func<List<IUser>, int,  bool>> ulContainsJohn = 
                (List<IUser> l, int min) =>  (l.Where(u => u.FirstName == "John").Count() > min);


    ulContainsJohn.Compile()(userList, min);
Nix
Can't change the signature. Please see the clarification I added. Good idea though.
Shlomo
Why don't u return the count?
Nix
+1  A: 

Edit: read your comment, try a function creator.

Func<int, Func<List<IUser>, bool>> createFn = (min) =>
    (l) => (l.Count(u => u.FirstName == "John") > min);

Func<List<IUser>, bool>> contains0 = createFn(0);

Assert.AreEqual(true, contains0(userList));

Func<List<IUser>, bool>> contains3 = createFn(3);

Assert.AreEqual(true, contains3(userList));

Try using a 1 element array. Ugly, but it works.

var values = new int[] { 0 };

Expression<Func<List<IUser>, bool>> ulContainsJohn = 
                (l => l.Where(u => u.FirstName == "John").Count() > values[0]);

Assert.AreEqual(true, ulContainsJohn.Compile()(userList));

values[0] = 3;

Assert.AreEqual(true, ulContainsJohn.Compile()(userList));

Another option, better:

private int Minimum { get; set; }

...

Expression<Func<List<IUser>, bool>> ulContainsJohn = 
            (l => l.Where(u => u.FirstName == "John").Count() > Minimum);

Func<List<IUser>, bool> fn = ulContainsJohn.Compile();
Assert.AreEqual(true, fn(userList));

Minimum = 3;

Assert.AreEqual(true, fn(userList));
sixlettervariables
Close enough. I need the expression tree. Thanks a lot.
Shlomo