我最近听说了C# 7.2中的新功能,现在我们可以返回值类型的引用(例如int
),甚至是只读的值类型引用。据我所知,值类型存储在堆栈中。当方法结束时,它们从堆栈中移除。那么当方法GetX
退出时,int
会发生什么?
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”,因为它不是 ref local(11,24)
为什么会出现这个错误?难道是因为该变量无法移到堆上所以无法工作吗?这是问题所在吗?我们只能返回不在堆上的值类型的引用吗?这两个问题是一个问题吗。
首先:按引用返回的值类型变量存放在哪里?栈还是堆?(我猜是堆,但为什么?)
其次:为什么不能通过引用返回在堆栈上创建的值类型?
因此,以下代码可以编译:
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
方法中,因此没有在堆栈中创建对吗?
ref
语法使运行时能够使用指针。指针可以生成更高效的代码,避免复制值,但它们也很危险。使用指向不再有效的内存位置的指针是一个非常经典的错误。C# 编译器会检查这些错误,它能够判断方法返回后局部变量已不存在,因此标记为糟糕的代码。https://en.wikipedia.org/wiki/Dangling_pointer - Hans Passant