2010-05-27 4 views
11

Выход из следующей программы:Статический конструктор может запускаться после нестатического конструктора. Это ошибка компилятора?

Non-Static 
Static 
Non-Static 

Является ли это ошибка компилятора? Я ожидал:

Static 
Non-Static 
Non-Static 

потому что я думал, что статический конструктор ВСЕГДА вызывался перед нестационарным конструктором.

Я тестировал это с помощью Visual Studio 2010 с использованием как .net 3.5, так и .net 4.0.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace StaticConstructorBug 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var mc = new MyClass(); 

      Console.ReadKey(); 
     } 
    } 

    public class MyClass 
    { 
     public MyClass() 
     { 
      Console.WriteLine("Non-static"); 
     } 

     static MyClass() 
     { 
      Console.WriteLine("Static"); 
     } 

     public static MyClass aVar = new MyClass(); 
    } 
} 
+0

Можете ли вы объяснить, почему вы ожидали, что? Потому что это не то, о чем говорит спецификация. –

ответ

11

См ECMA 334 §17.4.5.1:

17.4.5.1 Статическое поле инициализации

статическое поле переменной Инициализаторы декларации класса соответствуют последовательности заданий, которые выполняются в текстовый порядок, в котором они появляются в объявлении класса. Если в классе существует статический конструктор (§17.11) , выполняется инициализатор статического поля непосредственно перед выполнением этого статического конструктора . В противном случае, статического поля инициализаторы выполняются на время, зависящая от реализации до первого использования статического поля этого класса

В частности: «выполнение статического поля инициализаторов происходит непосредственно перед выполнением этот статический конструктор ".

Ваш static MyClass aVar должен быть инициализирован до того, как ваш статический конструктор выполнит (или, по крайней мере, должен появиться таким образом). Без этого статического члена статический конструктор должен вызываться перед любыми нестатическими конструкторами.

Если вы все еще хотите использовать одноэлементный номер MyClass, вы можете поместить его в класс контейнера и обратиться к нему, используя это, например.:

public static class MyClassSingleton 
{ 
    public static MyClass aVar = new MyClass(); 
} 
1

Этот public static MyClass aVar = new MyClass(); является частью вашего статического конструктора. Если вы посмотрите на него с отражателем, вы увидите следующее:

static MyClass() 
{ 
    aVar = new Program.MyClass(); 
    Console.WriteLine("Static"); 
} 

Итак, ваш результат должен быть очевиден.

0

Link Из MSDN:

Статический конструктор вызывается автоматически инициализировать класс перед первой инстанции создается или ссылаются любые статические члены.

Мое Угадайте, что это из-за статического экземпляра экземпляра на последней строке, но согласно MSDN статический конструктор должен произойти до того, как вызывается первый экземпляр.

+0

Да, так называется статический конструктор, он инициализирует элемент данных (построенный с помощью обычного конструктора), а затем управление возвращается в пользовательский статический конструктор, где он печатает строку. – Puppy

5

Это связано с линией public static MyClass aVar = new MyClass();.

Фактически aVar = new MyClass(); является префиксом статического контрструктора. Так что ваш статический конструктор:

static MyClass() { 
    Console.WriteLine("Static"); 
} 

изменяется на:

static MyClass() { 
    aVar = new MyClass(); // this will run instance contstructor and prints "Non-Static" 
    Console.WriteLine("Static"); 
}