2014-02-16 2 views
2

Получил сомнения относительно C# static/const member/local variables. Просто хочу знать, что происходит с памятью, выделенной неиспользуемым статическим/константным элементам/локальным переменным в C#, как память восстанавливается в следующем примере сценария?C# статические и константные переменные памяти

Вопрос о поведении памяти относительно статических и константных переменных [с учетом части памяти приложения - статического хранилища). Этот вопрос НЕ о сборке мусора. Речь идет о памяти и о том, что происходит с неиспользуемыми статическими и константными переменными, которые (также) имеют память?

Спагетти Код сниппета:

/// <summary> 
/// Skew your data with every-second-and-annoyed updates 
/// </summary> 
class Skewgle 
{ 
    static Skewgle cloneApele = new Skewgle(); 
    const Skewgle patentMoto = default(dynamic); 
    static int? dontBeEvilMotto = 1998; 
    const int ditchMotoToBeEvil = 2014; 

    static void Main() 
    { 
     const Skewgle findYourMailsAlreadyReadBetweenSpamTabs = patentMoto; 

     if (findYourMailsAlreadyReadBetweenSpamTabs == null) 
     { 
      System.Console.WriteLine("findYourMailsAlreadyReadBetweenSpamTabs and patentMoto are null"); 
     } 

     if (cloneApele != null) 
     { 
      System.Console.WriteLine("cloneApele is not null"); 
     } 

     System.Console.WriteLine("What about dontBeEvilMotto? ditchMotoToBeEvil?"); 
    } 
} 

Благодаря

+0

Отзыв, как и предполагалось. Кстати, на этот вопрос уже ответили Алексей Левенков и Кецалькоатль. Кудос ребята !!! – user3315496

ответ

5

Все статических полей класса будет инициализирован перед первым использованием любого экземпляра/статического метода класса (static field initialization in C# spec).

Статические поля для каждого приложения. Домен и значение не будут помечены для GC до разгрузки AppDomain.

4

MSDN: http://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx

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

Таким образом, вы не можете иметь patentMoto быть ничего, кроме null. Btw. default(dynamic) возвращает точно null. Вы могли бы нарисовать =null там, было бы проще прочитать. Вы будете никогда не имеют нулевой переменной «const object», кроме string. Но вы можете иметь тонны static с.

const и static никогда не были GC'ed до тех пор, пока AppDomain, который имеет их в памяти, не будет выгружен.

GC по определению очищает все, на что больше не ссылаются. Поскольку статическая переменная запоминает какой-либо объект, этот объект НЕ будет очищен до тех пор, пока существует переменная static. И он существует до тех пор, пока содержащий тип «существует», поэтому он перестает существовать только тогда, когда AppDomain выгружается. Если вы не создадите собственные дополнительные приложения и не выгрузите их «вручную» в какой-то момент времени, это означает, что они будут очищены при выходе программы.

Но это относится к автоматической очистке вещей, которые помнят переменная static. Вы можете выпускать тиги раньше - просто вы должны указать null ify статическую переменную. GC счищает объекты, а не переменные. (*)

Очевидно, что это невозможно для const, поэтому любая большая строка const занимает память навсегда. Что касается AppDomain - для const это сложнее: они фактически скомпилированы в сборку. Таким образом, они будут полностью очищены только после того, как сборка будет выгружена из памяти. Если сборка разделяется между приложениями, то она останется до тех пор, пока последняя не будет удалена. Константы являются постоянными и неизменными, поэтому не должно быть больно делиться ими. Помните, что все константные переменные объекта: null или строки. Других вариантов нет. Поэтому, если вы не создаете строку константы 4-Gb, вам не нужно беспокоиться об этом.

const в местном масштабе ничем не отличается. Это локальная переменная, но она все еще собрана в исходную сборку. См. Выше.

(*) Это означает, что если вы создадите класс с одним миллионом (1000000) статических переменных, то все его значения будут иметь, по крайней мере, около 4 МБ памяти до тех пор, пока домен приложения не будет выгружен. Это потому, что это один миллион нулевых указателей. В этом случае в GC нет ничего, кроме самого Типа.

+0

Благодарим вас за ввод и ответ. – user3315496

1

Основное отличие между константой и статикой заключается в расположении памяти. Все данные const находятся в том же пространстве памяти, что и исполняемый код, который является только для чтения-памятью (ROM), где статические данные загружаются в динамическую память, где вы можете читать и писать на ней. Теперь вот интересная часть, которая, кажется, была упущена в каждом из предыдущих ответов. Статические данные занимают пространство динамической памяти, но требуют дополнительного пространства ПЗУ и, в худшем случае, могут занимать в два раза больше объема памяти. Рассмотрим следующий пример:

class StaticData 
{ 
    static readonly int s_static1 = 1; 
    static readonly int s_static2 = 2; 
} 

class ConstData 
{ 
    const int CONST1 = 1; 
    const int CONST2 = 2; 
} 

Класс StaticData имеет две статические переменные s_static1 и s_static2, которые будут занимать динамическое пространство памяти 2 целых чисел. Однако оба они должны быть инициализированы, и поэтому для их инициализации также должен существовать код ROM. В этом примере и в зависимости от компилятора будет существовать как минимум 2 байта (или 2 целых числа хранения без оптимизации) пространства ПЗУ, необходимого только для хранения 2 постоянных значений (1 & 2) для инициализации статических переменных, а не чтобы указать исполняемый код ROM, необходимый для их инициализации.

Для класса ConstData требуется только место для хранения ПЗУ, и поэтому в большинстве случаев это наилучшее использование памяти.

Теперь это становится более интересным, если учесть, как данные используются компилятором. За исключением строковых/символьных данных, константы обычно заменяются непосредственно в коде в точке отсчета. Другими словами, постоянные значения непосредственно загружаются в регистр или помещаются в стек, в зависимости от использования. В случае статической переменной компилятор должен считывать это значение из памяти с помощью дополнительного кода (ссылка на указатель), и поэтому требуется дополнительный код ПЗУ.

Итак, вы почти всегда лучше используете «const» вместо «static readonly».

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