-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Background and motivation
There are several cases where the C# compiler treats a ref as implicitly scoped, where the compiler does not allow the ref to escape the method.
thisforstructinstance methodsrefparameters that refer toref structtypesoutparameters
For specific instances where the ref should be allowed to escape, we should provide a well-known attribute that the compiler will recognize that indicates the ref is not scoped.
See low-level-struct-improvements.md.
API Proposal
namespace System.Diagnostics.CodeAnalysis
{
[AttributeUsage(
AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter,
AllowMultiple = false,
Inherited = false)]
public sealed class RefEscapesAttribute : Attribute
{
}
}API Usage
When applied to struct instance methods and properties, this ref is unscoped.
struct S1
{
private int _field;
[RefEscapes] public ref int Property => ref _field; // ok
[RefEscapes] public ref int GetField() => ref _field; // ok
}When applied to a struct type, this ref is unscoped for all instance methods and properties.
[RefEscapes]
struct S2
{
private int _field;
public ref int Property => ref _field; // ok
public ref int GetField() => ref _field; // ok
}
[RefEscapes]
struct S3
{
private S2 _child;
public ref int Value => ref _child.Property; // ok
}When applied to a ref parameter, the ref is unscoped.
ref struct R { }
ref R ReturnRefStructRef(bool b, ref R x, [RefEscapes] ref R y)
{
if (b)
return ref x; // error: Cannot return parameter by reference
else
return ref y; // ok
}When applied to an out parameter, the ref is unscoped.
ref int ReturnOut(bool b, out int x, [RefEscapes] out int y)
{
x = 1;
y = 2;
if (b)
return ref x; // error: Cannot return parameter by reference
else
return ref y; // ok
}Alternative Designs
Without a well-known attribute recognized by the compiler, callers will need to use Unsafe.AsRef() and similar methods to return a scoped ref.
An alternative attribute name: UnscopedAttribute.
Risks
No response