views:

788

answers:

5

As a relative newbie I try to read as much as I can about a particular subject and test/write as much code as I can. I was looking at one of Jons Brainteasers (question #2) and my output was different than the answer. Which makes brings me here to ask if something has changed in recent versions and to see what output others are getting from this code.

The question is, "What will be displayed, why, and how confident are you?"

using System;

class Foo
{
    static Foo()
    {
        Console.WriteLine ("Foo");
    }
}

class Bar
{
    static int i = Init();

    static int Init()
    {
        Console.WriteLine("Bar");
        return 0;
    }
}

class Test
{
    static void Main()
    {
        Foo f = new Foo();
        Bar b = new Bar();
    }
}

What, if anything, would cause us to get two different answers?

+5  A: 

Jon's own answers page discusses this. I'm not a C# guy, but it seems like the system has exactly one choice of when to call the static foo code (and therefore write "Foo") but it has essentially infinite freedom to decide when to initialize Bar.i (which will write "Bar"), so it can happen either when the class is loaded, or when it is first used, or not at all.

jprete
A: 

Just looking at it, I'd be surprised if it displayed anything else but "FooBar".

For the simple reason you are accessing Foo first, so its static constructor will run. Followed by the static field initializer when instantiating Bar.

Happy to be corrected.

Wim Hollebrandse
+9  A: 

Now try it in release mode, outside of the debugger ;-p

I get different results with/without a debugger. The debugger upsets a lot of subtle nuances / optimisations, so I can only guess this is one of those times where the debugger matters. Which makes it even harder to debug ;-p

Marc Gravell
That exactly what I was missing.
Leroy Jenkins
I get 'Foo' in release mode, 'Foo'and'Bar' in Debug Mode. From a raw programming language standpoint, shouldn't both 'Foo' and 'Bar' be displayed in sequence?
sc_ray
+1  A: 

It prints Foo, Bar in Debug mode and Bar, Foo in Release mode. So what is happening is the Release code is optimized and the optimization causes Bar to be called first - but there is no guarantee that will always be the case.

Otávio Décio
Why does the optimization cause bar to be called first. What is the rule here?
Wil P
I would have to check, but I wouldn't be surprised if it is the debugger, more than debug/release, upsetting things. It regularly does.
Marc Gravell
Since bar doesn't have a static constructor, it can initialize the value for i and get the Bar class ready ahead of time. This prevents more work from happening later on. Alternatively, the debugger is letting Bar get initalized later. Foo, because it has the constructor, will always get initialized when first created, while Bar is free to be initialized anytime.
Will Eddins
@Marc - I ran both outside the IDE to get these results so I don't think the debugger is the factor here.
Otávio Décio
A: 

I think that foo bar will be printed. The static type constructor would be executed first in Foo, then the Init method would be called on the Bar class. I don't know about whether or not the behavior could change though. This is interesting.

Wil P