answer to C# quiz

Original quiz post is here:

  • it does compile
  • it gives no compiler warnings
  • the output is:
  • System.Linq.Enumerable+WhereEnumerableIterator`1[System.Char]
  • more obviously, the output is *not* "123456” as you might have expected
  • I posted the quiz because I had hit this behavior and it surprised me.  I wasn’t sure if I could “override” (in a weird way) something that’s already on the type (like ToString()).  I figured if it wouldn’t work, the compiler would at least warn me (but, of course, it didn’t).  I filed a bug about it, but I’d be surprised if the behavior changed 🙂

    What really strikes me as odd is that this means when you add extension methods to a type (even part of a public API), you’re taking a gamble that the type won’t add the same method+params itself – if/when it does, your next build will start calling a totally different method with likely different behavior, return values, side effects, etc.  All without ever doing anything in your code to say you wanted to call this new method.  And without ever getting warned about this potential ‘conflict’/’redirect’ situation.

    A real-world example of hitting this is the upcoming .NET 4.0 methods – I had added a CopyTo extension method awhile back to Stream (so I could take streams from SSRS and send them to the Response.Output stream in some pages).

    Now it turns out that in 4.0 the BCL team nicely added CopyTo to Stream!  When I upgraded the app to 4.0, I got no warnings about this situation (I only knew about it from keeping up with the 🙂

    Admittedly in this particular case the behavior is likely the same, but what if my version had doing a .Position = 0 on the source after the copy to the destination and I relied on that?

    IOW, without the compiler at least warning about this situation, you have what amounts to a breaking change (from my app’s perspective) brought in by a new framework that made a nice, innocuous, should-not-break-anything change.

    Perhaps I’m overreacting but it seems like the spirit of the C# compiler (at least, my very vague understanding of it 🙂 is being violated with the current behavior.