1

我有一个树视图,它代表一组记录的不同过滤器项目。在运行时,我将每个节点的标签设置为 Func 类型。例如:

myTreeView.Nodes.Add(New TreeNode("Node1"));
myTreeView.Nodes["Node1"].Tag = New Func<MyRecordType, bool>(p=> p.Title == "test 1");

myTreeView.Nodes.Add(New TreeNode("Node2"));
myTreeView.Nodes["Node2"].Tag = New Func<MyRecordType, bool>(p=> p.Title == "test 2");

ETC..

然后当用户点击节点时,我只需传递标签并将其用作获取数据的谓词:

gridView.DataSource = populateData(nodeClicked.Tag as Func<MyRecordType, bool>);

private MyRecordType[] populateData(Func<MyRecordType, bool> predicate)
{
  MyRecordType[] records;

  if(predicate == null)
     records = MyRecords.ToArray();
  else
    records = MyRecords.Where(predicate).ToArray();

  return records;
}

这一切都很好,但我添加了一些基于一组记录创建节点的代码。它看起来像这样:

var users = DB.MyRecords.OrderBy(o=> o.CreatedBy).Select(s=> s.CreatedBy).Distinct();

foreach(var user in users) {
  var node = new TreeNode("Node" + user, user);
  node.Tag = new Func<MyRecordType, bool>(p=> p.CreatedBy == user);
  MyTreeView.Nodes.Add(node);
}

问题是动态创建的节点都包含相同的谓词对象(这似乎是在最后一次 forsearch 迭代期间创建的相同谓词)。

我不太确定这里发生了什么。任何想法?太感谢了!

4

3 回答 3

2

您正在捕获一个非局部变量,即user.

在循环内创建一个临时文件并引用它。

例子:

foreach(var user in users) {
  var u = user;
  var node = new TreeNode("Node" + user, user);
  node.Tag = new Func<MyRecordType, bool>(p=> p.CreatedBy == u);
  MyTreeView.Nodes.Add(node);
}
于 2010-10-27T19:23:50.397 回答
0
(Func<MyRecordType, bool>)(p=> p.CreatedBy == user);

应该管用。

于 2010-10-27T19:23:15.103 回答
0

创建 Func<> 对象时,它不存储用户变量的当前值,而是对循环迭代共享的变量进行操作。但是,如果您在循环内创建变量的新副本,它将起作用。

例如,而不是:

        foreach (string s in new string[] { "1", "2", "3" })
            funcs.Add(() => s);

利用

        foreach (string s in new string[] { "1", "2", "3" })
        {
            string s1 = s;
            funcs.Add(() => s1);
        }
于 2010-10-27T19:32:17.053 回答