Использование статического конструктора (Jon Skeet Brainteaser) - PullRequest
18 голосов
/ 29 октября 2009

Как относительный новичок, я стараюсь читать как можно больше о конкретной теме и тестировать / писать как можно больше кода. Я смотрел на один из Jons Brainteasers (вопрос № 2), и мой вывод отличался от ответа. Это заставляет меня спросить, изменилось ли что-то в последних версиях, и посмотреть, что выводят другие из этого кода.

Вопрос: «Что будет отображаться, почему и насколько вы уверены?»

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();
    }
}

Что, если что-нибудь, заставило бы нас получить два разных ответа?

Ответы [ 5 ]

25 голосов
/ 29 октября 2009

Теперь попробуйте в режиме релиза, вне отладчика; -p

Я получаю разные результаты с / без отладчика. Отладчик расстраивает множество тонких нюансов / оптимизаций, поэтому я могу только догадываться, что это один из тех случаев, когда отладчик имеет значение. Что затрудняет отладку; -p

6 голосов
/ 29 октября 2009

Страница ответов Джона обсуждает это. Я не C # парень, но похоже, что у системы есть только один выбор, когда вызывать статический код foo (и, следовательно, писать "Foo"), но у нее по существу неограниченная свобода выбора, когда инициализировать Bar.i (который будет писать «Bar»), так что это может произойти либо при загрузке класса, либо при его первом использовании, либо вообще без него.

4 голосов
/ 29 октября 2009

Он печатает Foo, Bar в режиме отладки и Bar, Foo в режиме Release. Таким образом, происходит то, что код Release оптимизируется, и оптимизация заставляет вызывать Bar первым - но есть гарантия no , которая всегда будет иметь место.

0 голосов
/ 29 октября 2009

Я думаю, что foo bar будет напечатан. Конструктор статического типа будет сначала выполняться в Foo, затем вызываться метод Init для класса Bar. Я не знаю, может ли поведение измениться. Это интересно.

0 голосов
/ 29 октября 2009

Просто глядя на это, я был бы удивлен, если бы он отображал что-то еще, кроме "FooBar".

По той простой причине, что вы сначала обращаетесь к Foo, поэтому будет работать его статический конструктор. За ним следует инициализатор статического поля при создании экземпляра Bar.

Рад быть исправленным.

...