Fabulous Adventures In Coding

Eric Lippert's Blog

Psychic Debugging, Part One

Here is a compiler bug report I got the other day. The user is trying to write a unit test for a method which takes a Foo and returns a collection of Bars. The test is supposed to confirm that GetBars throws an exception if the argument is null. The test was failing with “got no exception”. The user was wondering if somehow the compiler had optimized away the call.

    static void Test() {
        bool gotException = false;
        try {
            IEnumerable<Bar> bars = Foo.GetBars(null);
        }
        catch (ArgumentNullException ex) {
            Console.WriteLine("SUCCESS: Got expected exception");
            gotException = true;
        }
        catch (Exception ex) {
            Console.WriteLine("FAILURE: Got unexpected exception");
            gotException = true;
        }
        finally {
            if (!gotException)
                Console.WriteLine("FAILURE: Got no exception");
        }
    }

Several people (including myself and Cyrus) psychically debugged this one independently. The user did not include the source code of GetBars, which is what necessitated the use of our psychic powers. Because I am a nice guy, I will give you the beginning:

    static public IEnumerable<Bar> GetBars(Foo foo) {
        if (foo == null)
            throw new ArgumentNullException("foo");

Our psychic powers correctly told us that the behaviour of the test program is correct and expected. What do your psychic powers tell you about the rest of the implementation of GetBars? What is going on here?

Published Wednesday, September 05, 2007 10:30 AM by Eric Lippert

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

kevinowen said:

My guess would be that GetBars is implemented using one or more "yield return" statements.

(The code in the method prior to the first occurrence of "yield return" isn't executed until it is needed, which won't be until the first call to MoveNext.)

September 5, 2007 2:16 PM
 

Karl said:

Something static in Foo is triggering an exception that is not caught by second catch.

September 5, 2007 2:21 PM
 

Wesner Moise said:

GetBars is an iterator method.

Iterators are deferred executed.

The Linq Enumerable class actually breaks up iterators into two methods,

the first of which validates the call immediately

and then calls the second method, which is the actual iterator.

September 5, 2007 2:43 PM
 

Bjorn said:

Foo could have a custom implementation of operator== which returns false when the right operand is null, so the (foo == null) condition doesn't hit.

September 5, 2007 4:29 PM
 

virtualblackfox said:

Same as keviowen and Wesner Moise the Iterator part in the C# 2.0 norm say :

"""invoking the function member does not immediately execute the code in the iterator block."""

So including a yield return in the body of Foo.GetBars will create this result.

I think that overloading operator== could also be an answer but with an IEnumerable<T> result sound a lot like an iterator :D

September 5, 2007 5:54 PM
 

Dean Harding said:

Yeah, the hint "What do your psychic powers tell you about the *rest of the implementation* of GetBars?" points me to the yield return solution as well, rather than the operator == one.

Mind you, if it WAS yield return, I'm not sure that it's a *compiler bug* -- that's the expected behaviour, isn't it?

Though I must admit that overloading operator == is tricky and has bittem me a couple of times like this too! :-)

September 5, 2007 7:42 PM
 

Thomas Eyde said:

Or, perhaps, there is an overload Foo(object)?

September 6, 2007 8:21 AM
 

Fabulous Adventures In Coding said:

A number of readers have the mysterious fifth sense which gives them the ability to deduce that the GetBars

September 6, 2007 11:41 AM
 

Fabulous Adventures In Coding said:

The other day I went to buy some snack from the snack machine in the kitchen. The snack I wanted was

September 8, 2008 1:34 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit

About Eric Lippert

Eric Lippert is a senior developer on the Microsoft C# compiler team. Before that he worked on the framework of Visual Studio Tools For Office. Before that, he worked on the compilers, runtimes and tools for VBScript, JScript, Windows Script Host and other Microsoft Scripting technologies. He lives in Seattle and spends his free time editing books about programming languages, playing the piano, and trying to keep his tiny sailboat upright in Puget Sound.

This Blog

Syndication


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker