Skip to content

Commit 28c5745

Browse files
authored
update readonly with new usages in new C# versions. (#6086)
* update `readonly` with new usages in new C# versions. * fix bad link * interim checkin * respond to feedback
1 parent e22a009 commit 28c5745

File tree

4 files changed

+104
-109
lines changed

4 files changed

+104
-109
lines changed

docs/csharp/language-reference/keywords/codesnippet/CSharp/readonly_1.cs

Lines changed: 0 additions & 12 deletions
This file was deleted.

docs/csharp/language-reference/keywords/codesnippet/CSharp/readonly_2.cs

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
title: "readonly (C# Reference)"
3-
ms.date: 07/20/2015
2+
title: "readonly keyword (C# Reference)"
3+
ms.date: 06/21/2018
44
f1_keywords:
55
- "readonly_CSharpKeyword"
66
- "readonly"
@@ -9,50 +9,89 @@ helpviewer_keywords:
99
ms.assetid: 2f8081f6-0de2-4903-898d-99696c48d2f4
1010
---
1111
# readonly (C# Reference)
12-
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+
1421
## 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:
16-
17-
[!code-csharp[csrefKeywordsModifiers#14](../../../csharp/language-reference/keywords/codesnippet/CSharp/readonly_1.cs)]
18-
19-
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:
2024

21-
- When the variable is initialized in the declaration, for example:
25+
[!code-csharp[Readonly Field example](~/samples/snippets/csharp/keywords/ReadonlyKeywordExamples.cs#ReadonlyField)]
2226

23-
```csharp
24-
public readonly int y = 5;
25-
```
27+
You can assign a value to a `readonly` field only in the following contexts:
2628

27-
- For an instance field, in the instance constructors of the class that 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+
public readonly int y = 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.
2839

2940
> [!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:
42+
43+
```csharp
3344
public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;
34-
```
35-
36-
## Comparing readonly and non-readonly instance fields
37-
[!code-csharp[csrefKeywordsModifiers#15](../../../csharp/language-reference/keywords/codesnippet/CSharp/readonly_2.cs)]
38-
39-
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:
62+
63+
[!code-csharp[readonly struct example](~/samples/snippets/csharp/keywords/ReadonlyKeywordExamples.cs#ReadonlyStruct)]
64+
65+
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+
public readonly struct Point
69+
{
70+
public readonly double X;
71+
public readonly double Y;
72+
73+
public Point(double x, double y) => (X, Y) = (x, y);
74+
75+
public override string ToString() => $"({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:
84+
85+
[!code-csharp[readonly struct example](~/samples/snippets/csharp/keywords/ReadonlyKeywordExamples.cs#ReadonlyReturn)]
86+
The type returned doesn't need to be a `readonly struct`. Any type that can be returned by `ref` can be returned by `ref readonly`
87+
4988
## C# Language Specification
50-
[!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)]
89+
[!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)]
5190

5291
## See Also
53-
[C# Reference](../../../csharp/language-reference/index.md)
54-
[C# Programming Guide](../../../csharp/programming-guide/index.md)
55-
[C# Keywords](../../../csharp/language-reference/keywords/index.md)
56-
[Modifiers](../../../csharp/language-reference/keywords/modifiers.md)
57-
[const](../../../csharp/language-reference/keywords/const.md)
58-
[Fields](../../../csharp/programming-guide/classes-and-structs/fields.md)
92+
[C# Reference](../../../csharp/language-reference/index.md)
93+
[C# Programming Guide](../../../csharp/programming-guide/index.md)
94+
[C# Keywords](../../../csharp/language-reference/keywords/index.md)
95+
[Modifiers](../../../csharp/language-reference/keywords/modifiers.md)
96+
[const](../../../csharp/language-reference/keywords/const.md)
97+
[Fields](../../../csharp/programming-guide/classes-and-structs/fields.md)

docs/csharp/language-reference/keywords/ref.md

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,19 @@ helpviewer_keywords:
1010
---
1111
# ref (C# Reference)
1212

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:
1414

1515
- 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-
1716
- In a method signature, to return a value to the caller by reference. See [Reference return values](#reference-return-values) for more information.
18-
1917
- 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.
2019

2120
## Passing an argument by reference
2221

2322
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.
2423

2524
> [!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.
2726
2827
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.
2928

@@ -42,6 +41,7 @@ class CS0663_Example
4241
public void SampleMethod(ref int i) { }
4342
}
4443
```
44+
4545
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.
4646

4747
[!code-csharp[csrefKeywordsMethodParams#6](../../../../samples/snippets/csharp/language-reference/keywords/in-ref-out-modifier/RefParameterModifier.cs#2)]
@@ -59,38 +59,39 @@ However, methods can be overloaded when one method has a `ref`, `in`, or `out` p
5959

6060
## Passing an argument by reference: An example
6161

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.
6363

6464
[!code-csharp[csrefKeywordsMethodParams#6](../../../../samples/snippets/csharp/language-reference/keywords/in-ref-out-modifier/RefParameterModifier.cs#3)]
6565

6666
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).
6767

6868
## Reference return values
6969

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.
7171

7272
A reference return value is defined by using the `ref` keyword:
7373

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+
public ref decimal GetCurrentValue()
78+
```
7579

76-
```csharp
77-
public ref decimal GetCurrentValue()
78-
```
7980
- Between the `return` token and the variable returned in a `return` statement in the method. For example:
80-
81-
```csharp
82-
return ref DecimalArray[0];
83-
```
8481

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+
return ref DecimalArray[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).
8687

8788
For an example, see [A ref returns and ref locals example](#a-ref-returns-and-ref-locals-example)
8889

8990
## Ref locals
9091

9192
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.
9293

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.
9495

9596
For example, the following statement defines a ref local value that is returned by a method named `GetEstimatedValue`:
9697

@@ -104,8 +105,8 @@ You can access a value by reference in the same way. In some cases, accessing a
104105
ref VeryLargeStruct reflocal = ref veryLargeStruct;
105106
```
106107

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+
109110
## A ref returns and ref locals example
110111

111112
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
116117

117118
[!code-csharp[csrefKeywordsMethodParams#6](../../../../samples/snippets/csharp/language-reference/keywords/in-ref-out-modifier/RefParameterModifier.cs#5)]
118119

119-
## C# Language Specification
120-
[!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)]
120+
## Ref struct declarations
121+
122+
## C# Language Specification
123+
124+
[!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)]
121125

122-
## See also
126+
## See also
127+
123128
[Reference semantics with value types](../../reference-semantics-with-value-types.md)
124129
[Passing Parameters](../../programming-guide/classes-and-structs/passing-parameters.md)
125130
[Method Parameters](method-parameters.md)

0 commit comments

Comments
 (0)