easy question about comparing collection using var in LINQ

T

Tony Johansson

Hello!

I have this foreach loop construction. Assume I loop 2 times in this loop
then I want to compare
the collection that is created the first lap and stored in myTest to the
collection that is stored in the same myTest
in the the second lap. How can I do that ?

foreach (string wsrID in myworkSheetRowID)
{
var myTest = paramInitiatorer.Where(p => p.WorksheetRowID ==
wsrID).Select(p => new {p.Parameter, p.Value});
}

//Tony
 
P

Pavel Minaev

I'm going to have to sleep on this, and figure out if I still really love 
variable capturing now as much as I used to.  I'm not sure how I feel  
about LINQ expressions being able to have their results change from one  
enumeration to another, just by changing the value of a captured variable..

It seems like a powerful and thus potentially useful behavior.  On the  
other hand, in this context the variable capturing is a bit more subtle  
than it usually is (at least to me), and so might be a more likely trap  
for someone to fall into.

Now, if only we had "readonly" for locals...
 
P

Pavel Minaev

Wouldn't help in this case.  The local variable involved _is_ read-only..  
It just happens to change implicitly under the compiler's control.  :)

Well that's not quite read-only, isn't it :)

Or perhaps I rather meant "immutable"...
Now that I've thought about it, I'm okay with variable capturing in this  
context.  It is a potential pitfall, but then it always is.  And  
special-casing the scenario would introduce arbitrary inconsistencies in  
the language, as well as prevent someone from making actual use of the  
capturing feature if they wanted to.

As I recall, someone (Eric Lippert?) explained why they did variable
capturing in for & foreach loops the way it did. They understood that
capturing the value of each iteration (as if the variable was declared
in the body of the loop) would be more convenient for the majority of
cases, and typically what the programmers would expect. Unfortunately,
the language spec has already defined precise semantics for those
loops via expansion to more primitive constructs, and the scope of the
range variable in the loop there was quite unambiguous, and it was
actually possible to have code that relied on it in some edge cases.
So, for backwards compatibility, they've left the expansion as it was,
and so we have this non-obvious capture semantics.
 
P

Pavel Minaev

Perhaps that makes more sense.  But you couldn't apply "immutable" to a 
loop variable.  Sort of negates the point of the loop variable.  :)

Inside for-loop, yes (because its semantics are explicitly defined in
terms of mutating the variable). Inside foreach-loop, no, if its
expansion would have been that a new local variable is bound to a next
sequence element on every iteration.
The fact is, the semantics are only "non-obvious" when one forgets the  
rules.  Perhaps "non-intuitive" is a better description, because they are  
in fact "obvious" if you remember how loop variables are scoped and how  
scoping affects captured variables.

Scoping is a related issue. Again, there is a good reason why variable
declared in for-loop is scoped the way it is. But for foreach-loop, it
could just as well be scoped strictly to the loop body with no ill
effects whatsoever - and it wouldn't be any more complicated than the
present rule. The reason why I find it more intuitive is because it
coincides with List.ForEach (and the use of lambdas in general). As it
is, the capture rules are different between "from x in xs" and
"foreach (x in xs)" for no good reason.
 
P

Pavel Minaev

But that's my point.  For "foreach" to have different semantics and  
scoping than "for" introduces an inconsistency in the language.

I dare say that "for" and "foreach" in C# (and other similar language)
actually have very little in common, simply because "for" is too
general-purpose - the latter doesn't even have to have a proper range
variable in a most general case! C-style "for" is really just a
shorthand way of writing a while loop; "foreach" is very different.

In fact, the difference is already quite evident from the fact that
"foreach" range variable is read-only within the loop - it further
reinforces the feel that the variable is not really mutated, but
rather we get a new one on every iteration.

Of course, language design is always about trade-offs, and I can
understand why they made this one. Still, the fact that the designers
themselves acknowledge that a different approach would be preferable
if not for backwards compatibility, it is a strong sign to me that the
existing design is not perfect.

Well, if you ask me, the "really correct" way of handling this would
be to dispose of "for" entirely, add a syntactic sugar for
Enumerable.Range, and use "foreach (int i in 0..10)" etc.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top