这个样本是否产生任何垃圾?

Dav*_*eia 2 c# performance xna

public class Foo
{
    public void Draw() // Called 60 times per second
    {
        spriteBatch.Draw(new Vector2(x, y), null, Color.White);
    }

    private float x, y;
}
Run Code Online (Sandbox Code Playgroud)

特别是,我想知道这个new Vector2(x, y)电话是否正在产生垃圾.

我的理解是,由于它Vector2是一个类型,并且没有存储为引用类型的成员,因此它将在堆栈上创建.因此,一旦Draw方法返回,它的内存应该自动回收,不会产生垃圾.

那是对的吗?


编辑

如果我可以要求进一步澄清Eric Lippert的首发帖子.

问题1)

它取决于被调用函数的第一个形式参数是采用引用类型还是值类型.如果它采用值类型然后否,则此处不会生成垃圾.如果它采用引用类型,则该值将被加框.

然后,如果签名碰巧是这样的:

public void Draw()
{
    Vector2 vector = new Vector2(x, y);
    spriteBatch.Draw(ref vector, null, Color.White);
}
Run Code Online (Sandbox Code Playgroud)

它会从盒子中生成垃圾?

问题2)

仅仅因为它不在堆上并不逻辑上需要它在堆栈上生成.它可能在一个寄存器中.

但我认为存储在寄存器中的行为就像从垃圾收集器的角度存储在堆栈中一样.那是对的吗?

Eri*_*ert 5

我想知道这个new Vector2(x, y)电话是否正在产生垃圾.

它取决于被调用函数的第一个形式参数是采用引用类型还是值类型.如果它采用值类型然后否,则此处不会生成垃圾.如果它采用引用类型,则该值将被加框.

我的理解是,由于Vector2是一个值类型,并且没有存储为引用类型的成员,它将在堆栈上创建

仅仅因为它不在堆上并不逻辑上需要它在堆栈上生成.它可能在一个寄存器中.

如果签名需要通过结构"通过ref"(使用"ref"或"out"修饰符)将有任何拳击?

不,你正在混合两种参考.作为变量别名的 "引用" 不是对象:

void D(int q) {}
void D(ref int q) {}
void D(object q) {}
Run Code Online (Sandbox Code Playgroud)

第一种方法D采用整数的副本.第二个D为包含未装箱整数的变量创建别名.第三个D采用盒装整数.

我假设存储在寄存器中的行为就像从垃圾收集器的角度存储在堆栈中一样.

这不是一个有效的假设.假设已注册或放置在堆栈上的值包含对垃圾收集对象的引用.抖动在其处理已注册引用的权限范围内与堆栈引用不同.例如,假设抖动的寄存器分配算法决定在抖动知道参考将不再被解除引用之后重新使用该寄存器.抖动完全自由,然后告诉垃圾收集器引用已经消失.通过这样做,即使在对象的方法正在执行时,GC线程也可能释放'this'.

抖动当然也可以通过堆栈自由地进行,但这将是一个更积极的优化.