I\'m playing with PropertyDescriptor and ICustomTypeDescriptor (still) trying to bind a WPF DataGrid to an object, for which the data is stored in a Dictionary.
Sinc
For some additional thoughts on this issue see
http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/
create a local copy of s
inside your for
loop and use that.
for(string s in this.Keys) {
string key = s;
//...
}
Simply:
foreach (string s in this.Keys)
{
string copy = s;
var descriptor = new PersonPropertyDescriptor(
copy,
new Func<object>(() => { return this[copy]; }),
new Action<object>(o => { this[copy] = o; }));
propList.Add(descriptor);
}
With captured variables, it is where it is declared that is important. So by declaring the captured variable inside the loop, you get a different instance of the capture-class per iteration (the loop variable, s
, is technically declared outside the loop).
Marc's solution is of course correct, but I thought I'd expand upon WHY below. As most of us know, if you declare a variable in a for
or foreach
statement, it only lives as long as what's inside, which makes it seem like the variable is the same as a variable declared in the statement-block of such a statement, but that's not right.
To understand it better, take the following for-loop. Then I'll re-state the "equivalent" loop in a while-form.
for(int i = 0; i < list.Length; i++)
{
string val;
list[i] = list[i]++;
val = list[i].ToString();
Console.WriteLine(val);
}
This works out to in while-form like below: (it isn't exactly the same, because continue
will act differently, but for scoping rules, it's the same)
{
int i = 0;
while(i < list.Length)
{
{
string val;
list[i] = list[i]++;
val = list[i].ToString();
Console.WriteLine(val);
}
i++;
}
}
When "exploded" out this way, the scope of the variables becomes clearer, and you can see why it always captures the same "s" value in your program, and why Marc's solution shows where to place your variable so that a unique one is captured every time.