Сколько экземпляров ValueType создает Майкл Джордан в стеке .NET?

Я немного запутался в том, как ValueType объекты управляются памятью в .NET. Я понимаю, что типы значений помещаются в стек для каждого экземпляра / объявления. Я не совсем уверен в том, что представляет собой новый экземпляр / объявление. Думаю, мой главный вопрос:

Если я передаю параметр ValueType методу, но не присваиваю ему значение, создается ли в стеке новый экземпляр?

Я не уверен, правильно ли я это формулирую, поэтому я написал простой пример программы, чтобы облегчить понимание моей путаницы.

void Main()
{
    //-------------------------|  Line 1:
    int MichaelJordan = 23;      
    //-------------------------|  Line 2:   
    int HoursInADay = 24;           
    //-------------------------|  Line 3:
    Console.WriteLine("Michael Jordan is "+(NumberHelper.Is23(MichaelJordan) ? string.Empty : "not ")+"23");
    //-------------------------|  Line 4:
    Console.WriteLine("The last number that wasn't 23 was "+NumberHelper.LastNumberThatWasnt23);
    //-------------------------|  Line 5:
    Console.WriteLine("Hours in a Day is "+(NumberHelper.Is23(HoursInADay) ? string.Empty : "not ")+"23");
    //-------------------------|  Line 6:  
    Console.WriteLine("The last number that wasn't 23 was "+NumberHelper.LastNumberThatWasnt23);
}

public static class NumberHelper {  
    public static int LastNumberThatWasnt23;
    public static bool Is23(int candidate){
        if(candidate != 23){
            LastNumberThatWasnt23 = candidate;
            return false;
        }
        return true;
    }
}

Итак, вот мои вопросы по программе.

  1. Сколько целочисленных экземпляров создается в стеке в этой программе?

  2. Где именно в коде создается каждый экземпляр типа значения в стеке?

Хотя есть большая вероятность, что я ошибаюсь, это то, что я думаю, происходит, и в чем я не уверен.

  • Строка 1: я знаю, что в стеке создан новый экземпляр для переменной MichaelJordan

  • Строка 2: я знаю, что в стеке создан новый экземпляр для переменной HoursInADay

  • Строка 3: Создается ли копия экземпляра значения из переменной MichaelJordan, чтобы быть параметром метода? Создан ли экземпляр значения 23 для сравнения?

  • Строка 4: значение поля LastNumberThatWasnt23 не инициализировано, поэтому возвращается значение по умолчанию. Создан ли для этого поля новый экземпляр со значением по умолчанию?

  • Строка 5: те же вопросы, что и Строка 3, но я также знаю, что в стеке создается новый экземпляр для поля LastNumberThatWasnt23, потому что я его устанавливаю.

  • Строка 6: Теперь в поле есть значение. Но, ссылаясь на это значение и передавая его в метод Console.WriteLine, создаю ли я новый экземпляр значения в стеке?

У меня есть еще одна часть этого вопроса: Как мне узнать о подобных вещах? Могу ли я сделать это программно? Есть ли какие-нибудь инструменты, которые можно использовать для раскрытия такой информации?

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


person smartcaveman    schedule 18.03.2011    source источник
comment
Ноль - он на пенсии. :)   -  person Kon    schedule 19.03.2011
comment
Лучший вопрос по программированию Майкла Джордана, который я видел на этой неделе   -  person kenwarner    schedule 19.03.2011
comment
Рекомендуемая литература: blogs.msdn.com/b/ericlippert/archive/2009/04/27/   -  person Odrade    schedule 19.03.2011


Ответы (3)


Это зависит от джиттера, который ваша машина использует для запуска этой программы. Но поскольку вы используете только две локальные переменные, очень вероятно, что правильный ответ - ноль. Оптимизатор jit сохраняет значения переменных в регистрах ЦП. Это одна из стандартных оптимизаций.

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

person Hans Passant    schedule 19.03.2011

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

Вы можете найти это, дизассемблировав код asm (не IL). И даже тогда это зависит от флагов компилятора, наличия отладчика, точного содержимого вашего метода, версии .net, ...

Но какое это вообще имеет значение? Память стека, потребляемая локальными переменными, незначительна, если вы не выполняете очень глубокую рекурсию.

person CodesInChaos    schedule 18.03.2011
comment
JIT, своевременный компилятор. Это та часть .NET, которая превращает код IL в реальный код процессора. - person David Yaw; 19.03.2011

выделение памяти для типов значений и ссылочных типов в. net framework должен ответить на большинство, если не на все ваши вопросы.

person Tomas Voracek    schedule 18.03.2011