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
@@ -3085,6 +3085,8 @@ Even though the syntax for accessing a property is the same as that for a field,
3085
3085
3086
3086
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.
3087
3087
3088
+
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`.
3089
+
3088
3090
### 14.7.2 Static and instance properties
3089
3091
3090
3092
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***.
@@ -5188,3 +5190,128 @@ When the body of the async function terminates, the return task is moved out of
5188
5190
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
5232
+
> }
5233
+
>set
5234
+
> {
5235
+
>this[idx.GetOffset(Length)] =value; // use the [int] indexer
5236
+
> }
5237
+
> }
5238
+
> }
5239
+
> ```
5240
+
>*endexample*
5241
+
5242
+
#### §indexable-sequence-impl-support-for-index Implicit Index support
5243
+
5244
+
Animplementationshallbehaveasifitprovidesaninstanceindexermemberwithasingleparameteroftype `System.Index` for any type that meets the following criteria:
5245
+
- 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*
5254
+
5255
+
### §indexable-sequence-support-for-range Providing support for Range
5256
+
5257
+
#### §indexable-sequence-expl-support-for-range Explicit Range support
5258
+
5259
+
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
5270
+
> {
5271
+
> get
5272
+
> {
5273
+
>intstartIdx=range.Start.GetOffset(Length);
5274
+
>intendIdx=range.End.GetOffset(Length);
5275
+
>intrangeLength=endIdx-startIdx;
5276
+
>BitArraynewBitArray=newBitArray(rangeLength);
5277
+
>for (inti=startIdx; i<endIdx; ++i)
5278
+
> {
5279
+
>newBitArray[i-startIdx] =this[i];
5280
+
> }
5281
+
>returnnewBitArray;
5282
+
> }
5283
+
> }
5284
+
> }
5285
+
> ```
5286
+
>*endexample*
5287
+
5288
+
#### §indexable-sequence-impl-support-for-range Implicit Range support
5289
+
5290
+
Animplementationshallbehaveasifitprovidesaninstanceindexermemberwithasingleparameteroftype `System.Range` for any type that meets the following criteria:
5291
+
- 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*
5294
+
- 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.
5295
+
5296
+
The provided instance indexer shall have the same accessibility and return type, including `ref` if present, as `Slice`.
5297
+
5298
+
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:
5303
+
> ```csharp
5304
+
> public BitArray Slice(intstartIdx, intrangeLength)
5305
+
> {
5306
+
>intendIdx=startIdx+rangeLength;
5307
+
>BitArraynewBitArray=newBitArray(rangeLength);
5308
+
>for (inti=startIdx; i<endIdx; ++i)
5309
+
> {
5310
+
>newBitArray[i-startIdx] =this[i];
5311
+
> }
5312
+
>returnnewBitArray;
5313
+
> }
5314
+
> ```
5315
+
*endnote*
5316
+
5317
+
>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