在方法中创建结构时,Ref return 不起作用
Ref return doesn't work when struct is created in the method
为什么这行不通?
我创建了结构并希望通过 ref.
return 它
public readonly struct AuditResult
{
public readonly bool AcceptChanges;
public readonly string Reason;
public AuditResult(bool acceptChanges, string reason)
{
AcceptChanges = acceptChanges;
Reason = reason;
}
public static ref AuditResult AcceptAuditResult()
{
var auditResult = (new AuditResult(true, string.Empty));
ref AuditResult res = ref auditResult;
return ref res;
}
}
发生此错误:
CS8157 Cannot return 'res' by reference because it was initialized to a value that cannot be returned by reference
在这种情况下,我的变量是 ref
?
C# documentation 指出:
The return value must have a lifetime that extends beyond the execution of the method. In other words, it cannot be a local variable in the method that returns it. It can be an instance or static field of a class, or it can be an argument passed to the method. Attempting to return a local variable generates compiler error CS8168, "Cannot return local 'obj' by reference because it is not a ref local."
为了使用 return ref
关键字,您需要 return 一个 而不是 局部变量的对象,因为局部变量将超出范围并被垃圾收集。相反,考虑 return 对 class/struct 中的成员变量的引用,而不是 res
。此外,请考虑是否需要通过引用 return 值 - 如果您不在内部其他地方访问它,则无需通过引用传递它。
但是请注意,您 可以 在本地使用 ref
关键字为局部变量名称创建别名,如下所示:
Foo a = new Foo();
ref Foo b = ref a;
这里,修改b
也会修改a
。但是,使用此语法,您无法在当前方法范围之外传递本地引用。
这是 C++ 或 Rust 等非托管语言中的常见错误 - 通过使用 ref
语义,您可以在决定管理自己的内存时有效地编写代码。
考虑以下 C++ 位:
char* Greet(char* name)
{
char buffer[100];
sprintf(buffer, "Hello, %s!", name);
return buffer;
}
方法退出后,buffer
超出作用域 - 它不再存在,您将留下一个悬空指针。这个模式叫做 RAII - Resource acquisition is initialization.
你正在尝试做类似的事情 -
ref var something = ...
return ref res;
该局部变量超出范围 - 您将尝试 return 引用不存在的内容。
但是为什么 ref return
首先存在?
通过引用返回意味着只复制引用,不复制结构。
有时,创建一个新结构可能代价高昂。
static readonly AuditResult AcceptWithNoReason =
new AuditResult(true, string.Empty);
public static ref readonly AuditResult AcceptAuditResult()
{
return ref AcceptWithNoReason; //this is valid
}
但是您确实必须 return 对生命周期比该方法调用更长的东西的引用。阅读更多 here.
为什么这行不通?
我创建了结构并希望通过 ref.
public readonly struct AuditResult
{
public readonly bool AcceptChanges;
public readonly string Reason;
public AuditResult(bool acceptChanges, string reason)
{
AcceptChanges = acceptChanges;
Reason = reason;
}
public static ref AuditResult AcceptAuditResult()
{
var auditResult = (new AuditResult(true, string.Empty));
ref AuditResult res = ref auditResult;
return ref res;
}
}
发生此错误:
CS8157 Cannot return 'res' by reference because it was initialized to a value that cannot be returned by reference
在这种情况下,我的变量是 ref
?
C# documentation 指出:
The return value must have a lifetime that extends beyond the execution of the method. In other words, it cannot be a local variable in the method that returns it. It can be an instance or static field of a class, or it can be an argument passed to the method. Attempting to return a local variable generates compiler error CS8168, "Cannot return local 'obj' by reference because it is not a ref local."
为了使用 return ref
关键字,您需要 return 一个 而不是 局部变量的对象,因为局部变量将超出范围并被垃圾收集。相反,考虑 return 对 class/struct 中的成员变量的引用,而不是 res
。此外,请考虑是否需要通过引用 return 值 - 如果您不在内部其他地方访问它,则无需通过引用传递它。
但是请注意,您 可以 在本地使用 ref
关键字为局部变量名称创建别名,如下所示:
Foo a = new Foo();
ref Foo b = ref a;
这里,修改b
也会修改a
。但是,使用此语法,您无法在当前方法范围之外传递本地引用。
这是 C++ 或 Rust 等非托管语言中的常见错误 - 通过使用 ref
语义,您可以在决定管理自己的内存时有效地编写代码。
考虑以下 C++ 位:
char* Greet(char* name)
{
char buffer[100];
sprintf(buffer, "Hello, %s!", name);
return buffer;
}
方法退出后,buffer
超出作用域 - 它不再存在,您将留下一个悬空指针。这个模式叫做 RAII - Resource acquisition is initialization.
你正在尝试做类似的事情 -
ref var something = ...
return ref res;
该局部变量超出范围 - 您将尝试 return 引用不存在的内容。
但是为什么 ref return
首先存在?
通过引用返回意味着只复制引用,不复制结构。 有时,创建一个新结构可能代价高昂。
static readonly AuditResult AcceptWithNoReason =
new AuditResult(true, string.Empty);
public static ref readonly AuditResult AcceptAuditResult()
{
return ref AcceptWithNoReason; //this is valid
}
但是您确实必须 return 对生命周期比该方法调用更长的东西的引用。阅读更多 here.