Skip to content

Commit 3522272

Browse files
committed
proofread and edit.
1 parent 718fc8b commit 3522272

File tree

1 file changed

+32
-52
lines changed

1 file changed

+32
-52
lines changed

proposals/csharp-7.0/tuples.md

Lines changed: 32 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ tuple_type_element
6868
6969
### Tuple types
7070

71-
Tuple types are declared with a syntax very similar to a parameter list:
71+
Tuple types are declared with the following syntax:
7272

7373
```csharp
7474
public (int sum, int count) Tally(IEnumerable<int> values) { ... }
@@ -157,18 +157,18 @@ byte y;
157157

158158
The evaluation order of deconstruction assignment expressions is "breadth first":
159159

160-
1. **Evaluate the LHS**. That means evaluate each of the expressions inside of it one by one, left to right, to yield side effects and establish a storage location for each.
161-
1. **Evaluate the RHS**. That means evaluate each of the expressions inside of it one by one, left to right to yield side effects
160+
1. Evaluate the LHS: Evaluate each of the expressions inside of it one by one, left to right, to yield side effects and establish a storage location for each.
161+
1. Evaluate the RHS: Evaluate each of the expressions inside of it one by one, left to right to yield side effects
162162
1. Convert each of the RHS expressions to the LHS types expected, one by one, left to right.
163-
1. Assign each of the conversion results from 3 to the storage locations found in 1.
163+
1. Assign each of the conversion results from 3 to the storage locations found in
164164

165165
> **Note to reviewers**: I found this in the LDM notes for July 13-16, 2016. I don't think it is still accurate:
166166
167167
A deconstructing assignment is a *statement-expression* whose type could be `void`.
168168

169169
### Duality with underlying type
170170

171-
Tuples map to underlying types of particular names -
171+
Tuples map to underlying types of particular names.
172172

173173
```csharp
174174
System.ValueTuple<T1, T2>
@@ -177,17 +177,17 @@ System.ValueTuple<T1, T2, T3>
177177
System.ValueTuple<T1, T2, T3,..., T7, TRest>
178178
```
179179

180-
Tuple types behave exactly like underlying types with only additional optional enhancement of the more expressive field names given by the programmer.
180+
Tuple types behave exactly like underlying types. The only additional enhancement is the more expressive field names given by the programmer.
181181

182182
```csharp
183183
var t = (sum: 0, count: 1);
184184
t.sum = 1; // sum is the name for the field #1
185185
t.Item1 = 1; // Item1 is the name of underlying field #1 and is also available
186186
187-
var t1 = (0, 1); // tuple omits the field names.
188-
t.Item1 = 1; // underlying field name is still available
187+
var t1 = (0, 1); // tuple omits the field names.
188+
t.Item1 = 1; // underlying field name is still available
189189
190-
t.ToString(); // ToString on the underlying tuple type is called.
190+
t.ToString(); // ToString on the underlying tuple type is called.
191191
192192
System.ValueTuple<int, int> vt = t; // identity conversion
193193
(int moo, int boo) t2 = vt; // identity conversion
@@ -202,7 +202,7 @@ var t1 = (Item1: 0, Item2: 1); // valid
202202
var t2 = (misc: 0, Item1: 1); // error: "Item1" was used in a wrong position
203203
```
204204

205-
If the tuple is bigger than the limit of 7, the implementation will nest the "tail" as a tuple into the eighth element recursively. This nesting is visible by accessing the `Rest` field of a tuple, but that field is considered an implementation detail, and is hidden from e.g. auto-completion, just as the `ItemX` field names are hidden but allowed when a tuple has named elements.
205+
If the tuple is bigger than the limit of 7, the implementation will nest the "tail" as a tuple into the eighth element recursively. This nesting is visible by accessing the `Rest` field of a tuple, but that field my be hidden from e.g. auto-completion, just as the `ItemX` field names may be hidden but allowed when a tuple has named elements.
206206

207207
A well formed "big tuple" will have names `Item1` etc. all the way up to the number of tuple elements, even though the underlying type doesn't physically have those fields directly defined. The same goes for the tuple returned from the `Rest` field, only with the numbers "shifted" appropriately.
208208

@@ -215,11 +215,11 @@ partial class C : IEnumerable<(string fullname, int)> { ... } // error: names mu
215215

216216
When tuple elements names are used in overridden signatures, or implementations of interface methods, tuple element names in parameter and return types must be preserved. It is an error for the same generic interface to be inherited or implemented twice with identity convertible type arguments that have conflicting tuple element names
217217

218-
### Overloading, overriding, hiding
219-
220-
For the purpose of overloading, overriding and hiding, tuples of the same types and lengths as well as their underlying ValueTuple types are considered equivalent. All other differences are immaterial. When overriding a member it is permitted to use tuple types with same or different field names than in the base member.
221-
222-
A situation where same field names are used for non-matching fields between base and derived member signatures, a warning is reported by the compiler.
218+
> note:
219+
>
220+
> For the purpose of overloading, overriding and hiding, tuples of the same types and lengths as well as their underlying ValueTuple types are considered equivalent. All other differences are immaterial. When overriding a member it is permitted to use tuple types with same or different field names than in the base member.
221+
>
222+
> A situation where same field names are used for non-matching fields between base and derived member signatures, a warning is reported by the compiler.
223223
224224
```csharp
225225
class Base
@@ -243,6 +243,8 @@ class InvalidOverloading
243243
}
244244
```
245245

246+
> endnote.
247+
246248
### Tuple field name erasure at runtime
247249

248250
Tuple field names aren't part of the runtime representation of tuples, but are tracked only by the compiler. As a result, the field names will not be available to a 3rd party observer of a tuple instance - such as reflection or dynamic code.
@@ -289,20 +291,24 @@ System.ValueTuple<int, int> vt = t; // identity conversion
289291
t2.moo = 1;
290292
```
291293

292-
That said, if you have an element name at one position on one side of a conversion, and the same name at another position on the other side, you almost certainly have bug in your code:
294+
> note:
295+
>
296+
> An element name at one position on one side of a conversion, and the same name at another position on the other side almost certainly have bug in the code:
293297
294298
```csharp
295299
(string first, string last) GetNames() { ... }
296300
(string last, string first) names = GetNames(); // Oops!
297301
```
298302

299-
Compilers should issue a warning for the preceding code.
303+
> Compilers should issue a warning for the preceding code.
304+
>
305+
> endnote.
300306
301307
### Boxing conversions
302308

303309
> The following text should be added to [Boxing conversions](../../spec/conversions.md#boxing-conversions) after the first paragraph:
304310
305-
As a *value_type*, tuples naturally have a boxing conversion. Importantly, the names aren't part of the runtime representation of tuples, but are tracked only by the compiler. Thus, once you've "cast away" the names, you cannot recover them. In alignment with the identity conversions, a boxed tuple will unbox to any tuple type that has the same element types in the same order.
311+
Tuples, like all value types, have a boxing conversion. Importantly, the names aren't part of the runtime representation of tuples, but are tracked only by the compiler. Thus, once you've "cast away" the names, you cannot recover them. In alignment with the identity conversions, a boxed tuple will unbox to any tuple type that has the same element types in the same order.
306312

307313
### Tuple conversions
308314

@@ -313,20 +319,13 @@ For the classification purpose, all element conversions are considered recursive
313319

314320
Tuple conversions are *Standard Conversions* and therefore can stack with user-defined operators to form user-defined conversions.
315321

316-
A tuple conversion can be classified as a valid instance conversion for an extension method invocation as long as all element conversions are applicable as instance conversions.
317-
318-
On top of the member-wise conversions implied by target typing, we can certainly allow implicit conversions between tuple types themselves.
319-
320-
Specifically, covariance seems straightforward, because the tuples are value types: As long as each member of the assigned tuple is assignable to the type of the corresponding member of the receiving tuple, things should be good.
321-
322322
An implicit tuple conversion is a standard conversion. It applies between two tuple types of equal arity when there is any implicit conversion between each corresponding pair of types.
323323

324324
An explicit tuple conversion is a standard conversion. It applies between two tuple types of equal arity when there is any explicit conversion between each corresponding pair of types.
325325

326-
```csharp
327-
(double sum, long count) weaken = Tally(...); // why not?
328-
(int s, int c) rename = Tally(...) // why not?
329-
```
326+
A tuple conversion can be classified as a valid instance conversion or an extension method invocation as long as all element conversions are applicable as instance conversions.
327+
328+
On top of the member-wise conversions implied by target typing, implicit conversions between tuple types themselves are allowed.
330329

331330
### Target typing
332331

@@ -338,25 +337,7 @@ A tuple literal is "target typed" when used in a context specifying a tuple type
338337
(string name, byte age) t = (null, 5); // Ok: the expressions null and 5 convert to string and byte
339338
```
340339

341-
In cases where the tuple literal is not part of a conversion, a tuple is used by its "natural type", which means a tuple type where the element types are the types of the constituent expressions. Since not all expressions have types, not all tuple literals have a natural type either:
342-
343-
```csharp
344-
var t = ("John", 5); // Ok: the type of t is (string, int)
345-
var t = (null, 5); // Error: tuple expression doesn't have a type because null does not have a type
346-
((1,2, null), 5).ToString(); // Error: tuple expression doesn't have a type
347-
348-
ImmutableArray.Create((()=>1, 1)); // Error: tuple expression doesn't have a type because lambda does not have a type
349-
ImmutableArray.Create(((Func<int>)(()=>1), 1)); // ok
350-
```
351-
352-
A tuple literal may include names, in which case they become part of the natural type:
353-
354-
```csharp
355-
var t = (name: "John", age: 5); // The type of t is (string name, int age)
356-
t.age++; // t has field named age.
357-
```
358-
359-
A successful conversion from tuple expression to tuple type is classified as an *ImplicitTuple* conversion, unless tuple's natural type matches the target type exactly, in such case it is an *Identity* conversion.
340+
A successful conversion from tuple expression to tuple type is classified as an *ImplicitTuple* conversion, unless the tuple's natural type matches the target type exactly, in such case it is an *Identity* conversion.
360341

361342
```csharp
362343
void M1((int x, int y) arg){...};
@@ -401,8 +382,6 @@ The `_` wildcard indicates that the one or more of the tuple fields are discarde
401382
Console.WriteLine($"Sum: {sum}, count was ignored");
402383
```
403384

404-
> Note: Should the `_` be added as a token? How was that resolved?
405-
406385
Any object may be deconstructed by providing an accessible `Deconstruct` method, either as a member or as an extension method. A `Deconstruct` method converts an object to a set of discrete values. The Deconstruct method "returns" the component values by use of individual `out` parameters. Deconstruct is overloadable.
407386

408387
The deconstructor pattern could be implemented as a member method, or an extension method:
@@ -445,13 +424,14 @@ p.Deconstruct(out byte __x, out byte __y);
445424

446425
> The following note should be added to the end of the section on [extension methods](../../spec/classes.md#extension-methods):
447426
448-
Note: Extension methods
449-
450-
on a tuple type apply to tuples with different element names:
427+
> note:
428+
>Extension methods on a tuple type apply to tuples with different element names:
451429
452430
```csharp
453431
static void M(this (int x, int y) t) { ... }
454432

455433
(int a, int b) t = ...;
456434
t.M(); // Sure
457435
```
436+
437+
> endnote.

0 commit comments

Comments
 (0)