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
Copy file name to clipboardExpand all lines: standard/classes.md
+127Lines changed: 127 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3049,6 +3049,8 @@ Even though the syntax for accessing a property is the same as that for a field,
3049
3049
3050
3050
When a property declaration includes an `extern` modifier, the property is said to be an ***external property***. Because an external property declaration provides no actual implementation, each of its *accessor_declarations* consists of a semicolon.
3051
3051
3052
+
A type is ***countable*** if it has a property named `Length` or `Count` with an accessible `get` accessor ([§14.7.3](classes.md#1473-accessors)) and a return type of `int`.
3053
+
3052
3054
### 14.7.2 Static and instance properties
3053
3055
3054
3056
When a property declaration includes a `static` modifier, the property is said to be a ***static property***. When no `static` modifier is present, the property is said to be an ***instance property***.
@@ -5087,3 +5089,128 @@ When the body of the async function terminates, the return task is moved out of
5087
5089
Ifthereturntypeoftheasyncfunctionis `void`, evaluationdiffersfromtheaboveinthefollowingway:Becausenotaskisreturned, thefunctioninsteadcommunicatescompletionandexceptionstothecurrentthread’s***synchronizationcontext***. Theexactdefinitionofsynchronizationcontextisimplementation-dependent, butisarepresentationof “where” thecurrentthreadisrunning. Thesynchronizationcontextisnotified when evaluation of a `void`-returning async function commences, completes successfully, or causes an uncaught exception to be thrown.
> Note to TG2 reviewers: Rationale for the choice of the name of the term *indexable sequence*: Various MS-hosted on-line pages use the term *sequence*. This word is already used quite a bit in the C# spec, in both a general sense as well as being defined in the context of query expressions. [§11.17 Query expressions|§11.17.1 General states: A query expression begins with a `from` clause and ends with either a `select` or `group` clause. The initial `from` clause may be followed by zero or more `from`, `let`, `where`, `join` or `orderby` clauses. Each `from` clause is a generator introducing a ***range variable*** that ranges over the elements of a ***sequence***. Each `let` clause introduces a range variable representing a value computed by means of previous range variables. …]. That definition is *not* applicable to indexes and ranges! The MS-provided proposal uses *collection*; however, that implies enumerable support, which is *not* required by indexes and ranges. (BTW, although it is used a lot in the C# spec, the term *collection* is *not* defined!) As such, rather than overload an existing term or invent a completely different one, I came up with *indexable sequence*.
Auser-definedtypecanprovideexplicitsupportforindexeraccess ([§11.7.10.3](expressions.md#117103-indexer-access)) using `System.Index` and `System.Range`. (See §indexable-sequence-expl-support-for-indexand §indexable-sequence-expl-support-for-range.) Ifvariouscriteriaaremet, anexistinguser-definedtypethatdoes *not* havesuchexplicitsupport, shallhaveprovidedforitbytheimplementationimplicitsupportforsuchindexerandrangeaccess. (See §indexable-sequence-impl-support-for-indexand §indexable-sequence-impl-support-for-range.) Inbothcases, thetypeisrecognizedasbeinganindexablesequencetype.
> returnthis[idx.GetOffset(Length)]; // use the [int] indexer
5131
+
> }
5132
+
>set
5133
+
> {
5134
+
>this[idx.GetOffset(Length)] =value; // use the [int] indexer
5135
+
> }
5136
+
> }
5137
+
> }
5138
+
> ```
5139
+
>*endexample*
5140
+
5141
+
#### §indexable-sequence-impl-support-for-index Implicit Index support
5142
+
5143
+
Animplementationshallbehaveasifitprovidesaninstanceindexermemberwithasingleparameteroftype `System.Index` for any type that meets the following criteria:
5144
+
- The type is countable [§14.7.1](classes.md#1471-general).
> *Note*:See §indexable-sequence-expl-support-for-index for an example of an explicitly provided `Index` indexer. If that were not defined, its equivalent would be provided by the implementation. *end note*
5153
+
5154
+
### §indexable-sequence-support-for-range Providing support for Range
5155
+
5156
+
#### §indexable-sequence-expl-support-for-range Explicit Range support
5157
+
5158
+
A type having an instance indexer taking a single argument of type `System.Range`, or a first argument of that type followed by optional arguments, may be indexed as described by [§11.7.10.3](expressions.md#117103-indexer-access).
> publicBitArraythis[Rangerange] // note the return type
5169
+
> {
5170
+
> get
5171
+
> {
5172
+
>intstartIdx=range.Start.GetOffset(Length);
5173
+
>intendIdx=range.End.GetOffset(Length);
5174
+
>intrangeLength=endIdx-startIdx;
5175
+
>BitArraynewBitArray=newBitArray(rangeLength);
5176
+
>for (inti=startIdx; i<endIdx; ++i)
5177
+
> {
5178
+
>newBitArray[i-startIdx] =this[i];
5179
+
> }
5180
+
>returnnewBitArray;
5181
+
> }
5182
+
> }
5183
+
> }
5184
+
> ```
5185
+
>*endexample*
5186
+
5187
+
#### §indexable-sequence-impl-support-for-range Implicit Range support
5188
+
5189
+
Animplementationshallbehaveasifitprovidesaninstanceindexermemberwithasingleparameteroftype `System.Range` for any type that meets the following criteria:
5190
+
- The type is countable [§14.7.1](classes.md#1471-general).
> *Note*:Asspecifiedin [§11.7.10.2](expressions.md#117102-array-access), for array access, the method `System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray` is used instead of `Slice`. *end note*
5193
+
- The type does not have an accessible instance indexer taking a `System.Range` as its only argument, or as its first argument with the remaining arguments being optional.
5194
+
5195
+
The provided instance indexer shall have the same accessibility and return type, including `ref` if present, as `Slice`.
5196
+
5197
+
When the type is indexed with a `System.Range`, the provided instance indexer shall take the given range and pass its start index and length as `int`s to `Slice` (or in the case of `string`, to method `Substring`).
>*Note*:See §indexable-sequence-expl-support-for-range for an example of an explicitly provided `Range` indexer. If that were not defined, its equivalent would be provided by the implementation, except that the provided indexer would call `Slice` to create and copy the slice. For type `BitArray`, `Slice` might be defined, as follows:
5202
+
> ```csharp
5203
+
> public BitArray Slice(intstartIdx, intrangeLength)
5204
+
> {
5205
+
>intendIdx=startIdx+rangeLength;
5206
+
>BitArraynewBitArray=newBitArray(rangeLength);
5207
+
>for (inti=startIdx; i<endIdx; ++i)
5208
+
> {
5209
+
>newBitArray[i-startIdx] =this[i];
5210
+
> }
5211
+
>returnnewBitArray;
5212
+
> }
5213
+
> ```
5214
+
*endnote*
5215
+
5216
+
>NotetoTG2reviewers:Setter:Whatifanythingshouldwesayaboutimplicitandexplicitsetterfor a Range indexer? Certainly, one can define a setter for a user-defined type; however, itisnotobviousastowhatsuchasetterwoulddo, especiallysinceitmustbeusedontheleft-handsideofassignmenttakingaright-handsideofthesametypeastheindexreturns. Inthecaseoftype `BitArray` thatwouldmeansomethinglike `ba1[range1] =ba2`, orperhaps `ba1[range1] =ba2[range2]`. AsfarasRexcoulddetermine, theoperationsonemightliketoimplementusingsuchasetterareprobablybestimplementedviaanamedmethod. Inanyevent, foracompiler-generatedRangeindexer, attemptingtouseitssetterresultsintheerrormessage “CS0131Theleft-handsideofanassignmentmustbeavariable, propertyorindexer,” whichsuggeststhegeneratedindexer **hasnosetter**. Ifthatisthecase, weshouldsaythatintheprevioussection.
0 commit comments