2015-02-12 2 views
1

Я знаю, что мы не инициализируем статический класс. Мы можем использовать их по имени класса. Но это должно быть в Статической памяти, чтобы мы могли их использовать. Когда статический класс попадает в статическую память? Это на RunTime или Lazy Loading?Инициализация статического класса в .NET

+1

Вы проверить это: https://msdn.microsoft.com/en-us/library/79b3xss3.aspx? –

+0

Статический класс просто «существует». Все поля, объявленные им, задаются в памяти при первой загрузке сборки. Однако, пока статический конструктор не выполняется, состояние и значения этих полей не инициализируются. –

+0

Я понятия не имею, что вы думаете о «статической памяти», и почему статический класс должен быть помещен в него. –

ответ

2

Я подозреваю, что вы думаете об этом как ленивый. Я не знаю, что вы подразумеваете под «статической памятью», но я думаю, что под этим стоит очень жизнеспособный вопрос о работе статических членов и о том, как они играют с памятью. Статические члены будут помещены в «обычную память», как и любые члены экземпляра.

Статические экземпляры помещаются в кучу во время загрузки (хотя это другой тип кучи, чем экземпляры, называемые High Frequency Heap), но не инициализируются до использования. В зависимости от того, какие статические члены у вас есть (а именно их типы, и являются ли эти типы ссылками или типами значений), это может быть большой или небольшой сделкой.

Например, если у вас есть массив байтов с 200 элементами, который будет загружен только при его использовании (за исключением null, который он изначально будет удерживать). Но если у вас есть 200 байтовых элементов, каждый из них будет помещен в память в начале.

Другими словами, перед использованием ClassA займет меньше памяти, чем ClassB, но во время использования они будут похожи. Конечно, не совсем то же самое, но вы можете представить себе тот момент, который я пытаюсь сделать.

static class ClassA 
{ 
    public static byte[] bytes = new byte[] { 1, 12 }; 
} 

static class ClassB 
{ 
    public static byte ByteA = 1; 
    public static byte ByteB = 12; 
} 

Это потому, что в ClassA, начальное значение bytes является null, но в ClassB, есть два значения, сохраненные от начала текущего процесса, оба из которых случаются быть 0. Вы можете себе представить, как это может играть в вещи с другими полями, основанными на значении или значении.

Другое различие вступает в игру, когда GC работает. Если я не ошибаюсь (хотя я не верю, что это поведение spec), статические члены не собираются мусором, пока процесс не прекратится. Однако, помимо этого, вы можете (свободно) думать о них как о простом экземпляре одиночного экземпляра класса, установленном компилятором.


Самый простой способ определить это «ленивой загрузки» значений будет разместить бокового осуществления вызова в статическом конструкторе. Нечто подобное,

public class Foo 
{ 
    static Foo() 
    { 
     Console.WriteLine("In static constructor!"); 
    } 

    public static void Bar() 
    { 
     Console.WriteLine("In Bar!"); 
    } 
} 

Put в контексте небольшого консольного приложения, вы можете легко определить, когда вызывается конструктор, и сделать вывод, что это тоже, когда статические члены помещаются в память.

void Main(string[] args) 
{ 
    Console.WriteLine("First line!"); 
    Foo.Bar(); 
    Console.WriteLine("Last line!"); 
} 

Эта программа outputs:

First line! 
In static constructor! 
In Bar! 
Last line! 

Вы также можете найти эту информацию в C# 5.0 спецификации (§10.12 статические конструкторы),

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

  • Создан экземпляр типа класса.
  • Ссылка на любой из статических членов типа класса.

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


Для того, чтобы вести мою точку дома, давайте посмотрим на последнюю пару методов.

static class Foo 
{ 
    public static int X = 2; 
    public static byte[] Bytes = new byte[] { 24, 66 }; 
} 
class Bar 
{ 
    public int X = 2; 
    public byte[] Bytes = new byte[] { 24, 66 }; 
} 

Пройдя через (на уровне IL), взаимодействия с этими классами будут совсем другими.

Рассмотрим метод:

void Main(string[] args) 
{ 
    // Foo is put into memory when the process spins up: 
    //  X : 0 
    //  Bytes : null 

    Console.Write(Foo.X); // During this line, Foo is initialized 
          //  X : 2 
          //  Bytes : 24, 66 

    Console.Write(Foo.X); // Nothing happens 

    Bar b = new Bar(); // During this line, Bar is put into memory, then initialized 
         //  X : 0, then "instantaneously" becomes 2 
         //  Bytes : null, then "instantaneously" becomes 24, 66 

    Console.Write(b.X); // Nothing happens 

    // Eventually, b will be cleared from memory by the garbage collector 
    // but Foo will not be, until the program closes. This sample is much 
    // too small to display that difference. 
} 
+0

Спасибо человек. который ответил на мой вопрос. – kibs

+0

Статическая память является синонимом HFH: всякий раз, когда процесс загружается в ОЗУ, мы можем сказать, что память примерно разделена на три области (внутри этого процесса): Stack, Heap и Static (что в .NET на самом деле специальная область внутри кучи, известная только как высокочастотная куча) http://www.codeproject.com/Articles/15269/Static-Keyword-Demystified – kibs

Смежные вопросы