MichaelJordan在.NET中的堆栈上创建了多少个ValueType实例?

时间:2011-03-18 23:40:59

标签: c# .net performance struct stack

我对如何在.NET中以内存方式管理ValueType对象感到困惑。我得到的值类型被放在每个实例/声明的堆栈上。我不太清楚什么构成了新的实例/声明。我认为我的主要问题是:

如果我将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. 在代码中,确切地说,是在堆栈上创建的每个值类型实例?

  3. 虽然我错了很有可能,但这就是我认为发生的事情,以及我不确定的事情。

    • 第1行:我知道在堆栈上为变量MichaelJordan创建了一个新实例

    • 第2行:我知道在堆栈上为变量HoursInADay创建了一个新实例

    • 第3行:是在变量MichaelJordan中创建的值实例的副本 为了成为方法参数?是否为比较创建了值23的实例?

    • 第4行: LastNumberThatWasnt23字段的值未初始化,因此返回默认值。是否为此字段创建了默认值的新实例?

    • 第5行:与第3行相同的问题,但是,我知道在字段LastNumberThatWasnt23的堆栈上创建了一个新实例,因为我正在设置它。

    • 第6行:现在,该字段有一个值。但是,在引用该值并将其传递到Console.WriteLine方法时,我是否在堆栈上创建了一个新的值实例?

    我还有一个问题,那就是我怎样才能找到这样的东西?我可以通过编程方式进行吗?是否有任何工具可用于揭示此类信息?

    我知道这是一个很长的问题,所以我感谢您花时间阅读它。

3 个答案:

答案 0 :(得分:3)

这取决于您的机器用于运行此程序的抖动。但由于您只使用两个局部变量,因此正确答案很可能为零。 jit优化器将变量值存储在CPU寄存器中。这是标准优化之一。

您可以找到有关抖动在this answer中执行的优化类型的更多信息。

答案 1 :(得分:2)

这很复杂。抖动是允许几乎自由的统治。它可以将局部变量放入寄存器,堆栈或两者,或者首先放在一个寄存器中。局部变量和堆栈分配之间没有简单的对应关系。

你可以通过反汇编asm代码(而不是IL)找到那些东西。即使这样,它依赖于编译标志,调试器的存在,方法的确切内容,.net版本......

但为什么一点都重要?局部变量消耗的堆栈内存可以忽略不计,除非你非常深入地进行递归。

答案 2 :(得分:1)

memory allocation of value types and reference types in .net framework应该回答大多数(如果不是全部)问题。