问题描述
我最近听说了 7.2 中的新 C# 功能,因此我们现在可以返回值类型的引用(例如 int
),甚至是值类型的只读引用.所以据我所知,一个值类型存储在堆栈中.当方法离开时,它们从堆栈中移除.那么当方法 GetX
退出时 int 会发生什么?
I recently heard about the new C# Feature in 7.2, so that we now can return a reference of value type (for example int
) or even a readonly reference of a value type. So as far as I know a value type is stored in the stack. And when the method is left, they are removed from stack. So what happens with the int when the method GetX
exits?
private ref int GetX()
{
// myInt is living on the stack now right?
int myInt = 5;
return ref myInt;
}
private void CallGetX()
{
ref int returnedReference = ref GetX();
// where does the target of 'returnedReference' live now?
// Is it somehow moved to the heap, because the stack of 'GetX' was removed right?
}
我收到错误
错误 CS8168:无法通过引用返回本地myInt",因为它不是本地引用 (11, 24)
为什么它不起作用?是不是因为变量不能移动到堆中而不起作用?这是问题吗?如果值类型不在堆栈中,我们是否只能通过引用返回值类型?我知道这是两个问题合二为一.
So why does it not work? Does it not work just because the variable can not be moved to the heap? Is this the problem? can we only return value types by reference if they do not live in the stack? I know that this are two question in one.
第一:ref 返回的值类型变量在哪里?堆栈还是堆?(我猜在堆上,但为什么)?
First: Where do value type-variables returned by ref live? Stack or heap? (I guess on the heap but why)?
第二:为什么栈上创建的值类型不能通过引用返回?
Second: Why can a value type created on the stack not be returned by reference?
所以这是可以编译的:
private int _myInt;
private ref int GetX()
{
// myInt is living on the stack now right?
_myInt = 5;
return ref _myInt;
}
private void CallGetX()
{
ref int returnedReference = ref GetX();
// where does the target of 'returnedReference' live now?
// Is it somehow moved to the heap? becase the stack of 'GetX' was removed right?
}
如果我理解你的评论,那是因为现在 _myInt 不在方法 GetX
中,因此没有在堆栈中创建,对吗?
If I understand your comments right it is because now the _myInt lives not inside the method GetX
and there fore is not created in the stack right?
推荐答案
我觉得你已经明白为什么它不起作用了.你不能通过方法引用返回局部变量(除非它是局部引用),因为在大多数情况下局部变量的生命周期就是方法,所以它在方法之外的引用没有任何意义(在方法之外此变量已失效,之前所在的位置可能包含任何内容).正如文档所述:
I feel like you understand yourself already why it does not work. You cannot return local variable by reference from method (unless it's ref local), because in most cases lifetime of local variable is the method, so its reference outside of method does not have any meaning (outside of method this variable is dead and location where it were before might contain anything). As documentation states:
返回值的生命周期必须超过方法的执行.换句话说,它不能是局部变量在返回它的方法中
在实践中,一些局部变量可能比它们声明的方法的执行时间更长.例如,闭包捕获的变量:
In practice some local variables might live longer than execution of method they are declared in. For example, variables captured by closure:
int myLocal = 5;
SomeMethodWhichAcceptsDelegate(() => DoStuff(myLocal));
return ref myLocal;
然而,这会引入额外的复杂性而没有任何好处,因此这也是被禁止的,即使 myLocal
的生命周期可能比包含方法长得多.
However, this introduces additional complications without any benefits, so this is also forbidden, even though lifetime of myLocal
might be much longer than containing method.
最好不要从堆栈和堆的角度考虑.例如,您可能认为您无法通过 ref return
从方法返回对堆栈上分配的某些内容的引用.事实并非如此,例如:
It's better to not think about it in terms of stack and heap. For example you might think that you cannot return reference to something allocated on stack from the method via ref return
. That's not true, for example:
private void Test() {
int myLocal = 4;
GetX(ref myLocal);
}
private ref int GetX(ref int i) {
return ref i;
}
这里myLocal
显然在栈上,我们通过引用GetX
来传递它,然后用return ref
返回这个(栈分配的)变量>.
Here myLocal
is clearly on stack, and we pass it by reference to GetX
and then return this (stack allocated) variable with return ref
.
所以只考虑变量生命周期而不是堆栈\堆.
So just think about it in terms of variable lifetimes and not stack\heap.
在您的第二个示例中,_myInt
字段的生命周期明显长于 GetX
的执行时间,因此通过引用返回它没有问题.
In your second example, lifetime of _myInt
field is clearly longer than execution of GetX
, so there is no problem to return it by reference.
另请注意,使用 return ref
返回值类型还是引用类型在此问题的上下文中没有任何区别.
Note also that whether you return value type or reference type with return ref
doesn't make any difference in context of this question.
这篇关于值类型变量(由 ref 返回)在哪里?堆栈还是堆?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!