我认为这涵盖了参考只读提案 https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/readonly-ref.md,安全退货规则部分。
从结构成员返回“this”不安全
这个你已经知道了。您可以阅读更多有关为什么不允许的信息here https://github.com/dotnet/csharplang/blob/master/meetings/2015/LDM-2015-09-01.md#this-in-structs。简而言之 - 允许它“污染本地值类型上调用的任何引用返回方法”,因此allref 从结构上的方法返回不是“安全返回”,因为它们可能包含对此的引用。
ref/in 参数可以安全返回
只要接收者是,实例结构字段就可以安全返回
安全返回
这涵盖了静态方法的情况。foo
参数可以安全返回(因为in
),因此,foo._x
可以安全返回,作为结构实例的字段,该实例本身可以安全返回。
如果所有引用/输出都可以安全地返回,则从另一个方法返回的引用
作为形式参数传递给该方法可以安全返回。
这可以防止上述静态方法出现问题。它使以下内容无效:
public static ref readonly int ExtensionGetX(in Foo foo) {
return ref foo._x;
}
static ref readonly int Test() {
var s = new Foo();
s._x = 2;
// fails to compile
return ref ExtensionGetX(s);
}
Because s
退货不安全,我们来自的参考ExtensionGetX
返回也不安全,因此我们不能将指针泄漏到范围之外的局部变量。
简而言之 - 它是允许的,因为它是安全的,并且没有禁止从结构成员方法返回对“this”的引用的特定缺点。
更新。我不认为更新你的问题会改变我的答案。上述“安全返回”规则保持不变。你变了in
to ref
, but ref
参数也可以安全返回。它的实例字段也是如此。但是如果你让参数返回不安全:
public static ref int GetXRef(Foo foo)
{
return ref foo._x;
}
那么就编译不了了。
您还认为(在评论中)“您不能将返回的引用存储为局部变量”,但事实并非如此:
ref int y = ref FooExtensions.GetXRef(ref f);
y = 10;
// print 10
Console.WriteLine(f.X);
所以,无论是否只读,in
or ref
- 安全返回规则确保在这种情况下返回 ref struct 成员是安全的,同时允许返回引用this
from struct local 方法会产生不良后果,强制将所有结构成员返回的所有引用值视为不安全返回。
如果结构成员可以将 ref 返回到,则将不可能发生什么的小例子this
:
public ref int GetXRefMember(ref int y) => ref y;
static ref int Test(ref int y) {
var x = new Foo();
// safe to return, but won't be if ref to `this` can
// ever be returned from struct local method
return ref x.GetXRefMember(ref y);
}