Skip to content

Commit c08930f

Browse files
pkulikovBillWagner
andauthored
Added more docs for ref fields (dotnet#31701)
* Added more docs for ref fields * Minor edits * Try to fix a xref link * Moved the spec links * Revert xref * Update docs/csharp/language-reference/builtin-types/ref-struct.md Co-authored-by: Bill Wagner <[email protected]> Co-authored-by: Bill Wagner <[email protected]>
1 parent cede979 commit c08930f

File tree

4 files changed

+40
-8
lines changed

4 files changed

+40
-8
lines changed

docs/csharp/language-reference/builtin-types/ref-struct.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "ref struct types - C# reference"
33
description: Learn about the ref struct type in C#
4-
ms.date: 09/15/2022
4+
ms.date: 10/12/2022
55
---
66
# `ref` structure types (C# reference)
77

@@ -18,8 +18,6 @@ You can use the `ref` modifier in the declaration of a [structure type](struct.m
1818

1919
You can define a disposable `ref struct`. To do that, ensure that a `ref struct` fits the [disposable pattern](~/_csharplang/proposals/csharp-8.0/using.md#pattern-based-using). That is, it has an instance or extension `Dispose` method, which is accessible, parameterless and has a `void` return type.
2020

21-
Beginning with C# 11, a `ref struct` may contain `ref` fields. To declare a `ref` field, use the same syntax as for declaring a [`ref` local variable](../statements/declarations.md#ref-locals). A `ref` field may be reassigned after it's initialized. The compiler ensures that a reference stored in a `ref` field doesn't outlive the value to which it refers. For information about the scope rules, see the [Scope of reference and values](../keywords/method-parameters.md#scope-of-references-and-values) section of the [Method parameters](../keywords/method-parameters.md) article.
22-
2321
Typically, you define a `ref struct` type when you need a type that also includes data members of `ref struct` types:
2422

2523
:::code language="csharp" source="snippets/shared/StructType.cs" id="SnippetRefStruct":::
@@ -30,15 +28,32 @@ To declare a `ref struct` as `readonly`, combine the `readonly` and `ref` modifi
3028

3129
In .NET, examples of a `ref struct` are <xref:System.Span%601?displayProperty=nameWithType> and <xref:System.ReadOnlySpan%601?displayProperty=nameWithType>.
3230

31+
## `ref` fields
32+
33+
Beginning with C# 11, you can declare a `ref` field in a `ref struct`, as the following example shows:
34+
35+
:::code language="csharp" source="snippets/shared/StructType.cs" id="SnippetRefField":::
36+
37+
A `ref` field may have the `null` value. Use the <xref:System.Runtime.CompilerServices.Unsafe.IsNullRef%60%601(%60%600@)?displayProperty=nameWithType> method to determine if a `ref` field is `null`.
38+
39+
You can apply the `readonly` modifier to a `ref` field in the following ways:
40+
41+
- `readonly ref`: You can [ref reassign](../operators/assignment-operator.md#ref-assignment) such a field with the `= ref` operator only inside a constructor or an [`init` accessor](../keywords/init.md). You can assign a value with the `=` operator at any point allowed by the field access modifier.
42+
- `ref readonly`: At any point, you cannot assign a value with the `=` operator to such a field. However, you can ref reassign a field with the `= ref` operator.
43+
- `readonly ref readonly`: You can only ref reassign such a field in a constructor or an `init` accessor. At any point, you cannot assign a value to the field.
44+
45+
The compiler ensures that a reference stored in a `ref` field doesn't outlive the value to which it refers. For information about the scope rules, see the [Scope of reference and values](../keywords/method-parameters.md#scope-of-references-and-values) section of the [Method parameters](../keywords/method-parameters.md) article.
46+
3347
## C# language specification
3448

3549
For more information, see the [Structs](~/_csharpstandard/standard/structs.md) section of the [C# language specification](~/_csharpstandard/standard/README.md).
3650

3751
For more information about features introduced in C# 7.2 and later, see the following feature proposal notes:
3852

53+
- [C# 7.2 - Compile-time safety for ref-like types](~/_csharplang/proposals/csharp-7.2/span-safety.md)
54+
- [C# 11 - ref fields and scoped](~/_csharplang/proposals/csharp-11.0/low-level-struct-improvements.md)
55+
3956
## See also
4057

4158
- [C# reference](../index.md)
4259
- [The C# type system](../../fundamentals/types/index.md)
43-
- [C# 7.2 - Compile-time safety for ref-like types](~/_csharplang/proposals/csharp-7.2/span-safety.md)
44-
- [C# 11 - ref fields and scoped](~/_csharplang/proposals/csharp-11.0/low-level-struct-improvements.md)

docs/csharp/language-reference/builtin-types/snippets/shared/StructType.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,23 @@ public ConversionRequest(double rate, ReadOnlySpan<double> values)
125125
public ReadOnlySpan<double> Values { get; }
126126
}
127127
// </SnippetReadonlyRef>
128+
129+
// <SnippetRefField>
130+
public ref struct RefFieldExample
131+
{
132+
private ref int number;
133+
134+
public int GetNumber()
135+
{
136+
if (System.Runtime.CompilerServices.Unsafe.IsNullRef(ref number))
137+
{
138+
throw new InvalidOperationException("The number ref field is not initialized.");
139+
}
140+
141+
return number;
142+
}
143+
}
144+
// </SnippetRefField>
128145
}
129146

130147
namespace parameterless_constructor

docs/csharp/language-reference/keywords/method-parameters.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ All of the changes that take place inside the method affect the original array i
8484
Methods can store the values of parameters in fields. When parameters are passed by value, that's always safe. Values are copied, and reference types are reachable when stored in a field. Passing parameters by reference safely requires the compiler to define when it's safe to assign a reference to a new variable. For every expression, the compiler defines a *scope* that bounds access to an expression or variable. The compiler uses two scopes: *safe_to_escape* and *ref_safe_to_escape*.
8585

8686
- The *safe_to_escape* scope defines the scope where any expression can be safely accessed.
87-
- The *ref_safe_to_escape* scope defines the scope where a *reference* to any expressions can be safely accessed or modified
87+
- The *ref_safe_to_escape* scope defines the scope where a *reference* to any expression can be safely accessed or modified.
8888

89-
Informally, you can think of these scopes as the mechanism to ensure your code never accesses or modifies a reference that's no longer valid. A reference is valid as long as it refers to a valid object or struct. The *safe_to_escape* scope defines when a variable can be assigned or reassigned. The *ref_safe_to_escape* scope defines when a variable can *ref* assigned or *ref* reassigned. Assignment assigns a variable to a new value. *ref assignment* assigns the variable to *refer to* a different storage location.
89+
Informally, you can think of these scopes as the mechanism to ensure your code never accesses or modifies a reference that's no longer valid. A reference is valid as long as it refers to a valid object or struct. The *safe_to_escape* scope defines when a variable can be assigned or reassigned. The *ref_safe_to_escape* scope defines when a variable can *ref* assigned or *ref* reassigned. Assignment assigns a variable to a new value; *ref assignment* assigns the variable to *refer to* a different storage location.
9090

9191
## Modifiers
9292

docs/csharp/language-reference/operators/assignment-operator.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ This is called *value assignment*: the value is assigned.
3434

3535
## ref assignment
3636

37-
*Ref assignment* `= ref` makes its left-hand operand an alias to the right-hand operand. The left-hand operand must be a [ref local](../keywords/ref.md#ref-locals), [ref readonly local](../keywords/ref.md#ref-readonly-locals), or a `ref` field in a [`ref struct`](../builtin-types/ref-struct.md). Both operands must be of the same type.
37+
*Ref assignment* `= ref` makes its left-hand operand an alias to the right-hand operand. The left-hand operand must be a [ref local](../keywords/ref.md#ref-locals), [ref readonly local](../keywords/ref.md#ref-readonly-locals), or a [`ref` field](../builtin-types/ref-struct.md#ref-fields) in a `ref struct`. Both operands must be of the same type.
3838

3939
The following example demonstrates the usage of the ref assignment operator:
4040

0 commit comments

Comments
 (0)