开发者

Lambda expression oddity

Long story short. I have 2 lists which contain the same type (but are used for different things) and I wan开发者_如何学JAVAt to know if EITHER list contains an item with a certain name.

My original code, which worked prefectly, was:

if (listA.Any(var => var.Name == strMatch) || listB.Any(var => var.Name == strMatch))
{
    //Do something
}

This code worked perfectly, whether the item was present in either or both lists. Later on, I had several 'impossible' crashes -- Things which never could have happened. I traced it back to that if statement NEVER returning true.

This stumped me for ages... I couldn't work out what was going wrong. Eventually I gave up and stuck brackets around the body of the lamda expressions like so...

if (listA.Any(var => (var.Name == strMatch)) || listB.Any(var => (var.Name == strMatch)))
{
    //Do something
}

After re-running my program, all the 'impossible' errors went away and it functioned normally. Removing the extra backets cause the errors to reappear.

I've never had this problem with lambda expressions before (especially where they work and THEN, after several runs working correctly break) and my other lambda expressions work correctly.

Example: The following code works 100% as expected (Assuming that there is a match in one of the lists)

Item item =
    ListA.FirstOrDefault(var => var.Name == strMatch) ??
    ListB.FirstOrDefault(var => var.Name == strMatch);

What's going on? Why is the compiler picky about some lamda expressions and not others? (Even when they are identical?) ???

UPDATE :: System Details This was encountered with Microsoft Visual Studio 2008 (Professional), Windows Vista 32bit.

UPDATE Video link, this has been test on other computers and is NOT reproducable. Makes me feel like my computer is doomed. Reinstallion of VS has no effect.

Please ignore any background cat noises, she only meows alot when she hears me recording something.


Those extra parentheses do not change the meaning of those lambda expressions, nor how the compiler chooses to compile those two different blocks of code. Based on what you've provided, there appears to be no functional difference between your two choices and thus the problem is unrelated to the parentheticals.

EDIT:

So I created a quick class that does exactly what you stated, and the IL differs only in class names. I used ildasm and windiff to confirm this. Nor does it change with /optimize- or /debug:full.

  .method /*06000005*/ public hidebysig 
          instance bool  '<Main>b__3'(class [mscorlib/*23000001*/]System.Tuple`2/*01000006*/<int32,string> var) cil managed
  // SIG: 20 01 02 15 12 19 02 08 0E
  {
    // Method begins at RVA 0x207c
    // Code size       22 (0x16)
    .maxstack  2
    .locals /*11000001*/ init ([0] bool CS$1$0000)
-   .line 29,29 : 69,92 ''
+   .line 29,29 : 67,88 ''
-   //000029:       if (listA.Any(var => (var.Item2 == strMatch)) || listB.Any(var => (var.Item2 == strMatch)))
+   //000029:       if (listA.Any(var => var.Item2 == strMatch) || listB.Any(var => var.Item2 == strMatch))
    IL_0000:  /* 03   |                  */ ldarg.1
    IL_0001:  /* 6F   | (0A)000005       */ callvirt   instance !1 class [mscorlib/*23000001*/]System.Tuple`2/*01000006*/<int32,string>/*1B000001*/::get_Item2() /* 0A000005 */
    IL_0006:  /* 02   |                  */ ldarg.0
-   IL_0007:  /* 7B   | (04)000001       */ ldfld      string Parentheses/*02000002*//'<>c__DisplayClass6'/*02000003*/::strMatch /* 04000001 */
+   IL_0007:  /* 7B   | (04)000001       */ ldfld      string NoParentheses/*02000002*//'<>c__DisplayClass6'/*02000003*/::strMatch /* 04000001 */
    IL_000c:  /* 28   | (0A)000006       */ call       bool [mscorlib/*23000001*/]System.String/*01000007*/::op_Equality(string, string) /* 0A000006 */
    IL_0011:  /* 0A   |                  */ stloc.0
    IL_0012:  /* 2B   | 00               */ br.s       IL_0014

Nota bene: there are two of these generated, one for each of the listX.Any calls. Both only differ in their comments. The generated IL is identical.

EDIT 2:

The output from ildasm for Visual Studio 2008 (csc 3.5.30729.4926) is also no different, so I'm really unable to say why in your instance of VS2k8 it dies besides perhaps the version of LINQ you have is bugged or the compiler on that machine has a bugged Expression generator, because I cannot replicate any difference.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜