Подтвердить что ты не робот

Использование статического конструктора (Jon Skeet Brainteaser)

Как относительный новичок, я стараюсь читать как можно больше о конкретном предмете и тестировать/писать как можно больше кода. Я смотрел на один из 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();
    }
}

Что, если угодно, вызовет у нас два разных ответа?

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

Благодарим вас за исправление.

Ответ 5

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