开发者

Running Into a Snag With Func

I have a treeview that represents different filter items to a set of records. At runtime, I am setting each node's tag to a Func type. For example:

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

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

etc..

Then when the user clicks on the node, I simply pass the Tag and use it as a predicate for getting my data:

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

This was all working great, but I added some code that creates nodes based on a set of records. It looks like this:

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

The problem is that the nodes that are created dynamically all contain the same predicate object (which seems to be the same predicate created during the last forearch iteration).

I'm not really sure what's going on here. Any idea? Thanks a million!


You are capturing a non-local variable, namely user.

Create a temporary inside the loop and refer to that instead.

Example:

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


(Func<MyRecordType, bool>)(p=> p.CreatedBy == user);

should work.


When you create the Func<> object, it does not store the current value of the user variable, and rather operates on the variable shared by the loop iteration. It will work, howerver, if you create a new copy of the variable inside the loop.

E.g., instead of:

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

use

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜