代码之家  ›  专栏  ›  技术社区  ›  Glenn Slayden

C#结构用作函数的返回值时是否装箱?

  •  6
  • Glenn Slayden  · 技术社区  · 14 年前

    一个简单的问题,但是我还没有找到关于堆栈溢出的确切答案。

        struct MyStruct { int x, y, z; }
    
        MyStruct GetMyStruct() => new MyStruct();
    
        static void Main()
        {
            var x = GetMyStruct();      // can boxing/unboxing ever occur?
        }
    

    是一个 C级# 结构(值类型) 从函数返回时复制到堆栈,不管它有多大?我不确定的原因是,对于MSIL以外的某些指令集(如x86),返回值通常需要放入处理器寄存器,而堆栈不直接涉及。

    如果是的话,是调用站点在 清除 (预期)值返回类型的堆栈?

    [编辑:回复摘要:]对于原问题的意图,答案是“否”;答案是 清除 不会(默默地)仅仅为了将结构作为返回值发送而装箱。

    2 回复  |  直到 5 年前
        1
  •  10
  •   Hans Passant    10 年前

    这是JIT编译器的一个重要实现细节。一般来说,如果struct足够小并且有简单的成员,那么它将在CPU寄存器中返回。如果它太大,则调用代码在堆栈上保留足够的空间,并将指向该空间的指针作为额外的隐藏参数传递。

    除非方法的返回类型是 对象 当然。

        2
  •  6
  •   Brian Rasmussen    14 年前

    当你想把一个结构当作一个 object ,所以如果你打电话 Func

    例如,这样做

     object o = Func();
    

    将产生以下IL

    L_0000: call valuetype TestApp.foo TestApp.Program::Func()
    L_0005: box TestApp.foo
    L_000a: stloc.0 
    

    这表明返回值是装箱的,因为我们将它赋给类型的引用 对象

    如果你把它赋给 Foo 它没有装箱,因此它被复制,值存储在堆栈中。