You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The `readonly` keyword is a modifier that you can use on fields. When a field declaration includes a `readonly` modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
13
-
12
+
13
+
The `readonly` keyword is a modifier that can be used in three contexts:
14
+
15
+
- In a [field declaration](#readonly-field-example), `readonly` indicates that assignment to the field can only occur as part of the declaration or in a constructor in the same class.
16
+
- In a [`readonly struct` definition](#readonly-struct-example), `readonly` indicates that the `struct` is immutable.
17
+
- In a [`ref readonly` method return](#ref-readonly-return-example), the `readonly` modifier indicates that method returns a reference and writes are not allowed to that reference.
18
+
19
+
The final two contexts were added in C# 7.2.
20
+
14
21
## Readonly field example
15
-
In this example, the value of the field `year` cannot be changed in the method `ChangeYear`, even though it is assigned a value in the class constructor:
You can assign a value to a `readonly` field only in the following contexts:
22
+
23
+
In this example, the value of the field `year` cannot be changed in the method `ChangeYear`, even though it is assigned a value in the class constructor:
20
24
21
-
- When the variable is initialized in the declaration, for example:
25
+
[!code-csharp[Readonly Field example](~/samples/snippets/csharp/keywords/ReadonlyKeywordExamples.cs#ReadonlyField)]
22
26
23
-
```csharp
24
-
publicreadonlyinty=5;
25
-
```
27
+
You can assign a value to a `readonly` field only in the following contexts:
26
28
27
-
-Foraninstancefield, intheinstanceconstructorsoftheclassthat contains the field declaration, or for a static field, in the static constructor of the class that contains the field declaration. These are also the only contexts in which it is valid to pass a `readonly` field as an [out](../../../csharp/language-reference/keywords/out-parameter-modifier.md) or [ref](../../../csharp/language-reference/keywords/ref.md) parameter.
29
+
- When the variable is initialized in the declaration, for example:
30
+
31
+
```csharp
32
+
publicreadonlyinty=5;
33
+
```
34
+
35
+
- In an instance constructor of the class that contains the instance field declaration.
36
+
- In the static constructor of the class that contains the static field declaration.
37
+
38
+
These constructor contexts are also the only contexts in which it is valid to pass a `readonly` field as an [out](out-parameter-modifier.md) or [ref](ref.md) parameter.
28
39
29
40
> [!NOTE]
30
-
> The `readonly` keyword is different from the [const](../../../csharp/language-reference/keywords/const.md) keyword. A `const` field can only be initialized at the declaration of the field. A `readonly` field can be initialized either at the declaration or in a constructor. Therefore, `readonly` fields can have different values depending on the constructor used. Also, while a `const` field is a compile-time constant, the `readonly` field can be used for runtime constants as in the following example:
31
-
32
-
```csharp
41
+
> The `readonly` keyword is different from the [const](const.md) keyword. A `const` field can only be initialized at the declaration of the field. A `readonly` field can be initialized either at the declaration or in a constructor. Therefore, `readonly` fields can have different values depending on the constructor used. Also, while a `const` field is a compile-time constant, the `readonly` field can be used for runtime constants as in the following example:
In the preceding example, if you use a statement like this:
40
-
41
-
`p2.y = 66; // Error`
42
-
43
-
you will get the compiler error message:
44
-
45
-
`The left-hand side of an assignment must be an l-value`
46
-
47
-
which is the same error you get when you attempt to assign a value to a constant.
48
-
45
+
```
46
+
47
+
[!code-csharp[Initialize readonly Field example](~/samples/snippets/csharp/keywords/ReadonlyKeywordExamples.cs#InitReadonlyField)]
48
+
49
+
In the preceding example, if you use a statement like the following example:
50
+
51
+
`p2.y = 66; // Error`
52
+
53
+
you will get the compiler error message:
54
+
55
+
`The left-hand side of an assignment must be an l-value`
56
+
57
+
which is the same error you get when you attempt to assign a value to a constant.
58
+
59
+
## Readonly struct example
60
+
61
+
The `readonly` modifier on a `struct` definition declares that the struct is **immutable**. Every instance field of the `struct` must be marked `readonly`, as shown in the following example:
The preceding example uses [readonly auto properties](../../properties.md#read-only) to declare its storage. That instructs the compiler to create `readonly` backing fields for those properties. You could also declare `readonly` fields directly:
66
+
67
+
```csharp
68
+
publicreadonlystructPoint
69
+
{
70
+
publicreadonlydoubleX;
71
+
publicreadonlydoubleY;
72
+
73
+
publicPoint(doublex, doubley) => (X, Y) = (x, y);
74
+
75
+
publicoverridestringToString() =>$"({X}, {Y})";
76
+
}
77
+
```
78
+
79
+
Adding a field not marked `readonly` generates compiler error `CS8340`: "Instance fields of readonly structs must be readonly."
80
+
81
+
## Ref readonly return example
82
+
83
+
The `readonly` modifier on a `ref return` indicates that the returned reference cannot be modified. The following example returns a reference to the origin. It uses the `readonly` modifier to indicate that callers cannot modify the origin:
Copy file name to clipboardExpand all lines: docs/csharp/language-reference/keywords/ref.md
+26-21Lines changed: 26 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,20 +10,19 @@ helpviewer_keywords:
10
10
---
11
11
# ref (C# Reference)
12
12
13
-
The `ref` keyword indicates a value that is passed by reference. It is used in three different contexts:
13
+
The `ref` keyword indicates a value that is passed by reference. It is used in four different contexts:
14
14
15
15
- In a method signature and in a method call, to pass an argument to a method by reference. See [Passing an argument by reference](#passing-an-argument-by-reference) for more information.
16
-
17
16
- In a method signature, to return a value to the caller by reference. See [Reference return values](#reference-return-values) for more information.
18
-
19
17
- In a member body, to indicate that a reference return value is stored locally as a reference that the caller intends to modify or, in general, a local variable accesses another value by reference. See [Ref locals](#ref-locals) for more information.
18
+
- In a `struct` declaration to declare a `ref struct` or a `ref readonly struct`. See [ref struct declarations](#ref-struct-declarations) for more information.
20
19
21
20
## Passing an argument by reference
22
21
23
22
When used in a method's parameter list, the `ref` keyword indicates that an argument is passed by reference, not by value. The effect of passing by reference is that any change to the argument in the called method is reflected in the calling method. For example, if the caller passes a local variable expression or an array element access expression, and the called method replaces the object to which the ref parameter refers, then the caller’s local variable or the array element now refers to the new object when the method returns.
24
23
25
24
> [!NOTE]
26
-
> Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by `ref` regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.
25
+
> Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by `ref` regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.
27
26
28
27
To use a `ref` parameter, both the method definition and the calling method must explicitly use the `ref` keyword, as shown in the following example.
29
28
@@ -42,6 +41,7 @@ class CS0663_Example
42
41
publicvoidSampleMethod(refinti) { }
43
42
}
44
43
```
44
+
45
45
However, methods can be overloaded when one method has a `ref`, `in`, or `out` parameter and the other has a value parameter, as shown in the following example.
@@ -59,38 +59,39 @@ However, methods can be overloaded when one method has a `ref`, `in`, or `out` p
59
59
60
60
## Passing an argument by reference: An example
61
61
62
-
The previous examples pass value types by reference. You can also use the `ref` keyword to pass reference types by reference. Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller. The storage location of the object is passed to the method as the value of the reference parameter. If you change the value in the storage location of the parameter (to point to a new object), you also change the storage location to which the caller refers. The following example passes an instance of a reference type as a `ref` parameter.
62
+
The previous examples pass value types by reference. You can also use the `ref` keyword to pass reference types by reference. Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller. The storage location of the object is passed to the method as the value of the reference parameter. If you change the value in the storage location of the parameter (to point to a new object), you also change the storage location to which the caller refers. The following example passes an instance of a reference type as a `ref` parameter.
For more information about how to pass reference types by value and by reference, see [Passing Reference-Type Parameters](../../../csharp/programming-guide/classes-and-structs/passing-reference-type-parameters.md).
67
67
68
68
## Reference return values
69
69
70
-
Reference return values (or ref returns) are values that a method returns by reference to the caller. That is, the caller can modify the value returned by a method, and that change is reflected in the state of the object that contains the method.
70
+
Reference return values (or ref returns) are values that a method returns by reference to the caller. That is, the caller can modify the value returned by a method, and that change is reflected in the state of the object that contains the method.
71
71
72
72
A reference return value is defined by using the `ref` keyword:
73
73
74
-
- In the method signature. For example, the following method signature inidicates that the `GetCurrentPrice` method returns a <xref:System.Decimal> value by reference.
74
+
- In the method signature. For example, the following method signature indicates that the `GetCurrentPrice` method returns a <xref:System.Decimal> value by reference.
75
+
76
+
```csharp
77
+
publicrefdecimalGetCurrentValue()
78
+
```
75
79
76
-
```csharp
77
-
publicrefdecimalGetCurrentValue()
78
-
```
79
80
- Between the `return` token and the variable returned in a `return` statement in the method. For example:
80
-
81
-
```csharp
82
-
returnrefDecimalArray[0];
83
-
```
84
81
85
-
In order for the caller to modify the object's state, the reference return value must be stored to a variable that is explicitly defined as a [ref local](#ref-locals).
82
+
```csharp
83
+
returnrefDecimalArray[0];
84
+
```
85
+
86
+
In order for the caller to modify the object's state, the reference return value must be stored to a variable that is explicitly defined as a [ref local](#ref-locals).
86
87
87
88
For an example, see [A ref returns and ref locals example](#a-ref-returns-and-ref-locals-example)
88
89
89
90
## Ref locals
90
91
91
92
A ref local variable is used to refer to values returned using `return ref`. A ref local variable must be initialized and assigned to a ref return value. Any modifications to the value of the ref local are reflected in the state of the object whose method returned the value by reference.
92
93
93
-
You define a ref local by using the `ref` keyword before the variable declaration, as well as immediately before the call to the method that returns the value by reference.
94
+
You define a ref local by using the `ref` keyword before the variable declaration, as well as immediately before the call to the method that returns the value by reference.
94
95
95
96
For example, the following statement defines a ref local value that is returned by a method named `GetEstimatedValue`:
96
97
@@ -104,8 +105,8 @@ You can access a value by reference in the same way. In some cases, accessing a
104
105
refVeryLargeStructreflocal=refveryLargeStruct;
105
106
```
106
107
107
-
Note that in both examples the `ref` keyword must be used in both places, or the compiler generates error CS8172, "Cannot initialize a by-reference variable with a value."
108
-
108
+
Note that in both examples the `ref` keyword must be used in both places, or the compiler generates error CS8172, "Cannot initialize a by-reference variable with a value."
109
+
109
110
## A ref returns and ref locals example
110
111
111
112
The following example defines a `Book` class that has two <xref:System.String> fields, `Title` and `Author`. It also defines a `BookCollection` class that includes a private array of `Book` objects. Individual book objects are returned by reference by calling its `GetBookByTitle` method.
@@ -116,10 +117,14 @@ When the caller stores the value returned by the `GetBookByTitle` method as a re
0 commit comments