2010-08-06 75 views
1

鉴于此代码:LINQ的功能/表达当地评估

 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)); 

列表中包含1“约翰”,但第二断言失败。我如何将min的值急切地绑定到Func,所以它不会尝试重新评估变量min?

说明:我不想更改签名。我希望表达式树不是作为变量来评估,而是作为一个常量表达式。无论如何要转换min的评估,以便树有一个常量表达式而不是变量评估?

+0

为什么?你想解析表达式树吗? – SLaks 2010-08-06 14:34:15

+0

你有一个悖论......你想要一个不断的表达......但你的测试正在改变它? – Nix 2010-08-06 14:56:47

+0

我希望函数ulContainsJohn中min bound的值作为一个常量表达式。 min可以改变,函数内的值不应该改变。现在有道理吗? – Shlomo 2010-08-06 15:49:27

回答

1

编辑:阅读你的评论,尝试函数的创造者。

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)); 

尝试使用1元素数组。丑,但它的作品。

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)); 

另一种选择,更好:

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)); 
+0

足够接近。我需要表达式树。非常感谢。 – Shlomo 2010-08-06 19:54:58

0

最简单的解决方案是让一个独立的变量:

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

请参阅我添加的说明... – Shlomo 2010-08-06 14:24:16

1

你必须使它成为一个参数。

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


    ulContainsJohn.Compile()(userList, min); 
+0

无法更改签名。请参阅我添加的说明。好主意,但。 – Shlomo 2010-08-06 14:23:37

+0

为什么不回你的计数? – Nix 2010-08-06 14:57:44