AralıklarRanges
ÖzetSummary
Bu özellik, oluşturma ve nesneleri sağlayan iki yeni işleç teslim etmek ve bunları çalışma zamanında System.Index System.Range dizin/dilim koleksiyonları için kullanmakla ilgilidir.This feature is about delivering two new operators that allow constructing System.Index and System.Range objects, and using them to index/slice collections at runtime.
Genel BakışOverview
İyi bilinen türler ve üyelerWell-known types and members
ve için yenintactic formlarını kullanmak üzere, hangintactic formların kullanıldıklarına bağlı olarak, yeni iyi bilinen System.Index System.Range türler ve üyeler gerekli olabilir.To use the new syntactic forms for System.Index and System.Range, new well-known types and members may be necessary, depending on which syntactic forms are used.
"hat" işleci () ^ kullanmak için aşağıdakiler gereklidirTo use the "hat" operator (^), the following is required
namespace System
{
public readonly struct Index
{
public Index(int value, bool fromEnd);
}
}
Türü bir System.Index dizi öğesi erişiminde bağımsız değişken olarak kullanmak için aşağıdaki üye gereklidir:To use the System.Index type as an argument in an array element access, the following member is required:
int System.Index.GetOffset(int length);
söz .. System.Range dizimi için System.Range türün yanı sıra aşağıdaki üyelerden biri veya daha fazlası gerekir:The .. syntax for System.Range will require the System.Range type, as well as one or more of the following members:
namespace System
{
public readonly struct Range
{
public Range(System.Index start, System.Index end);
public static Range StartAt(System.Index start);
public static Range EndAt(System.Index end);
public static Range All { get; }
}
}
Söz .. dizimi, bağımsız değişkenlerinin her ikisini birden veya hiçbirinin eksik olmasına izin verir.The .. syntax allows for either, both, or none of its arguments to be absent. Bağımsız değişken sayısından bağımsız olarak oluşturucu söz Range dizimi kullanmak için her zaman Range yeterlidir.Regardless of the number of arguments, the Range constructor is always sufficient for using the Range syntax. Ancak, diğer üyelerden herhangi biri varsa ve bağımsız değişkenlerden biri veya .. daha fazlası eksikse, uygun üyenin yerini alan üye olabilir.However, if any of the other members are present and one or more of the .. arguments are missing, the appropriate member may be substituted.
Son olarak, bir dizi öğesi erişim ifadesinde kullanılacak türünde bir System.Range değer için aşağıdaki üyenin mevcut olması gerekir:Finally, for a value of type System.Range to be used in an array element access expression, the following member must be present:
namespace System.Runtime.CompilerServices
{
public static class RuntimeHelpers
{
public static T[] GetSubArray<T>(T[] array, System.Range range);
}
}
System.IndexSystem.Index
C# bir koleksiyonun en baştan dizin oluşturması için bir yol yoktur, ancak çoğu dizinci "başlangıç" ifadesini kullanır veya bir "uzunluk - i" ifadesi kullanır.C# has no way of indexing a collection from the end, but rather most indexers use the "from start" notion, or do a "length - i" expression. " Ucundan" anlamına gelen yeni bir Dizin ifadesi tanıtıyoruz.We introduce a new Index expression that means "from the end". Özellik, yeni birli ön ek "hat" işleci tanıtacak.The feature will introduce a new unary prefix "hat" operator. Tek işleneni' olarak System.Int32 dönüştürülebilir.Its single operand must be convertible to System.Int32. Uygun fabrika yöntemi çağrısına System.Index indirecek.It will be lowered into the appropriate System.Index factory method call.
Aşağıdaki ek söz dizimi unary_expression dil bilgisini geliştirin:We augment the grammar for unary_expression with the following additional syntax form:
unary_expression
: '^' unary_expression
;
Buna end işlecinden dizin çağrılır.We call this the index from end operator. Uç işleçlerden önceden tanımlanmış dizin aşağıdaki gibidir:The predefined index from end operators are as follows:
System.Index operator ^(int fromEnd);
Bu işleç davranışı yalnızca sıfırdan büyük veya sıfıra eşit giriş değerleri için tanımlanır.The behavior of this operator is only defined for input values greater than or equal to zero.
Örnekler:Examples:
var array = new int[] { 1, 2, 3, 4, 5 };
var thirdItem = array[2]; // array[2]
var lastItem = array[^1]; // array[new Index(1, fromEnd: true)]
System.RangeSystem.Range
C# içinde koleksiyonların "aralıklarına" veya "dilimlerine" erişmek için sözdizmsel bir yol yoktur.C# has no syntactic way to access "ranges" or "slices" of collections. Genellikle kullanıcılar, bellek dilimlerini filtrelemek/çalıştırmak için karmaşık yapılar uygulamaya zorlar veya gibi LINQ yöntemlerine list.Skip(5).Take(2) başvurur.Usually users are forced to implement complex structures to filter/operate on slices of memory, or resort to LINQ methods like list.Skip(5).Take(2). ve diğer benzer türlerin ekleriyle, bu tür bir işlemi dil/çalışma zamanı içinde daha derin bir düzeyde desteklemek ve arabirimin birleştirilmiş hale sahip olmak System.Span<T> daha önemli hale gelir.With the addition of System.Span<T> and other similar types, it becomes more important to have this kind of operation supported on a deeper level in the language/runtime, and have the interface unified.
Dil, yeni bir aralık işleci x..y tanıtacak.The language will introduce a new range operator x..y. bu, iki ifadeyi kabul eden bir ikili düzeltme işlecidir.It is a binary infix operator that accepts two expressions. İşleci atlanabilir (aşağıdaki örneklerde) ve dönüştürülebilir olması System.Index gerekir.Either operand can be omitted (examples below), and they have to be convertible to System.Index. Uygun fabrika yöntemi çağrısına System.Range düşürülecek.It will be lowered to the appropriate System.Range factory method call.
Yeni bir öncelik düzeyi multiplicative_expression için C# dil bilgisi kurallarını aşağıdakilerle değiştiririz:We replace the C# grammar rules for multiplicative_expression with the following (in order to introduce a new precedence level):
range_expression
: unary_expression
| range_expression? '..' range_expression?
;
multiplicative_expression
: range_expression
| multiplicative_expression '*' range_expression
| multiplicative_expression '/' range_expression
| multiplicative_expression '%' range_expression
;
Aralık işlecinin tüm biçimleri aynı önceliğe sahip olur.All forms of the range operator have the same precedence. Bu yeni öncelik grubu, birli işleçlerden daha düşüktür ve çokplikli aritmetik işleçlerden daha yüksektir.This new precedence group is lower than the unary operators and higher than the multiplicative arithmetic operators.
işlecine .. range işleci çağrılır.We call the .. operator the range operator. Yerleşik aralık işleci kabaca bu formun yerleşik işlecinin çağrılma biçimine karşılık olarak anlaşılabilir:The built-in range operator can roughly be understood to correspond to the invocation of a built-in operator of this form:
System.Range operator ..(Index start = 0, Index end = ^0);
Örnekler:Examples:
var array = new int[] { 1, 2, 3, 4, 5 };
var slice1 = array[2..^3]; // array[new Range(2, new Index(3, fromEnd: true))]
var slice2 = array[..^3]; // array[Range.EndAt(new Index(3, fromEnd: true))]
var slice3 = array[2..]; // array[Range.StartAt(2)]
var slice4 = array[..]; // array[Range.All]
Ayrıca, çok boyutlu imzalar üzerinde tamsayıları ve dizinleri aşırı yükleme ihtiyacının önüne geçerek ' den örtülü System.Index System.Int32 bir dönüştürmeye sahip olmalıdır.Moreover, System.Index should have an implicit conversion from System.Int32, in order to avoid the need to overload mixing integers and indexes over multi-dimensional signatures.
Mevcut kitaplık türlerine Dizin ve Aralık desteği eklemeAdding Index and Range support to existing library types
Örtülü Dizin desteğiImplicit Index support
Dil, aşağıdaki ölçütlere uyan türler için tek parametreli bir Index örnek dizin üyesi sağlar:The language will provide an instance indexer member with a single parameter of type Index for types which meet the following criteria:
- Tür Countable'dır.The type is Countable.
- türü, bağımsız değişken olarak tek bir alan erişilebilir bir örnek
intdizine sahip.The type has an accessible instance indexer which takes a singleintas the argument. - Türün, birinci parametre olarak alan erişilebilir bir örnek
Indexdizine sahip değildir.The type does not have an accessible instance indexer which takes anIndexas the first parameter. tekIndexparametre olmalıdır veya kalan parametreler isteğe bağlı olmalıdır.TheIndexmust be the only parameter or the remaining parameters must be optional.
türü, veya adlı bir özelliğine ve bir dönüş türüne sahipse Length Countable'dır. Count intA type is Countable if it has a property named Length or Count with an accessible getter and a return type of int. Dil, bu özelliği kullanarak türünde bir ifadeyi ifadenin noktasındaki bir ifadeye dönüştürmek için, türü Index int kullanmaya hiç gerek Index kalmadan kullanabilir.The language can make use of this property to convert an expression of type Index into an int at the point of the expression without the need to use the type Index at all. Hem hem de Length mevcut olması durumunda tercih Count Length edilir.In case both Length and Count are present, Length will be preferred. Daha sonra kolaylık sağlamak için, teklif veya temsil etmek Length için adını Count Length kullanır.For simplicity going forward, the proposal will use the name Length to represent Count or Length.
Bu tür türler için dil, formun bir dizin üyesi gibi davranır; burada, stil ek açıklamaları dahil olmak üzere tabanlı T this[Index index] T dizin int oluşturmanın dönüş türü ref olur.For such types, the language will act as if there is an indexer member of the form T this[Index index] where T is the return type of the int based indexer including any ref style annotations. Yeni üye, dizin oluşturma ile eşleşen get set erişilebilirliği olan ve int üyelerine sahip olur.The new member will have the same get and set members with matching accessibility as the int indexer.
Yeni dizin oluşturma, türün bağımsız değişkenine dönüştürülerek ve tabanlı dizine Index int çağrı yayarak int uygulanır.The new indexer will be implemented by converting the argument of type Index into an int and emitting a call to the int based indexer. Tartışma amacıyla örneğini kullan o receiver[expr] zaman.For discussion purposes, let's use the example of receiver[expr]. dönüştürmesi expr int aşağıdaki gibi gerçekleşir:The conversion of expr to int will occur as follows:
- bağımsız değişkeni formda olduğunda ve
^expr2türüexpr2intolduğunda, değerinereceiver.Length - expr2çevrilir.When the argument is of the form^expr2and the type ofexpr2isint, it will be translated toreceiver.Length - expr2. - Aksi takdirde, olarak
expr.GetOffset(receiver.Length)çevrilir.Otherwise, it will be translated asexpr.GetOffset(receiver.Length).
Bu, geliştiricilerin özelliği Index değişiklike gerek kalmadan mevcut türlerde kullanmalarını sağlar.This allows for developers to use the Index feature on existing types without the need for modification. Örneğin:For example:
List<char> list = ...;
var value = list[^1];
// Gets translated to
var value = list[list.Count - 1];
Yan receiver Length etkilerin yalnızca bir kez yürütülmelerini sağlamak için ve ifadeleri uygun şekilde taşmalarını sağlar.The receiver and Length expressions will be spilled as appropriate to ensure any side effects are only executed once. Örneğin:For example:
class Collection {
private int[] _array = new[] { 1, 2, 3 };
public int Length {
get {
Console.Write("Length ");
return _array.Length;
}
}
public int this[int index] => _array[index];
}
class SideEffect {
Collection Get() {
Console.Write("Get ");
return new Collection();
}
void Use() {
int i = Get()[^1];
Console.WriteLine(i);
}
}
Bu kod "3. Uzunluğu Al" yazacak.This code will print "Get Length 3".
Örtülü Aralık desteğiImplicit Range support
Dil, aşağıdaki ölçütlere uyan türler için tek parametreli bir Range örnek dizin üyesi sağlar:The language will provide an instance indexer member with a single parameter of type Range for types which meet the following criteria:
- Tür Countable'dır.The type is Countable.
- türü, türünde iki parametreye
Slicesahip adlı erişilebilir bir üyeyeintsahip.The type has an accessible member namedSlicewhich has two parameters of typeint. - Türün ilk parametre olarak tek bir alan örnek
Rangedizineci yok.The type does not have an instance indexer which takes a singleRangeas the first parameter. tekRangeparametre olmalıdır veya kalan parametreler isteğe bağlı olmalıdır.TheRangemust be the only parameter or the remaining parameters must be optional.
Bu tür türler için dil, formun bir dizin üyesi gibi bağlanacak ve burada, stil ek açıklamalarını içeren yöntemin dönüş T this[Range range] T türü Slice ref olur.For such types, the language will bind as if there is an indexer member of the form T this[Range range] where T is the return type of the Slice method including any ref style annotations. Yeni üye ile eşleşen erişilebilirliği de Slice olacak.The new member will also have matching accessibility with Slice.
Tabanlı dizin oluşturma, adlı bir ifadeye bağlı olduğunda, ifade daha sonra yöntemine geçirilen iki değere Range receiver Range dönüştürülerek Slice düşürülecek.When the Range based indexer is bound on an expression named receiver, it will be lowered by converting the Range expression into two values that are then passed to the Slice method. Tartışma amacıyla örneğini kullan o receiver[expr] zaman.For discussion purposes, let's use the example of receiver[expr].
için ilk Slice bağımsız değişken, aralık türüne sahip ifade aşağıdaki şekilde dönüştürülerek elde edilir:The first argument of Slice will be obtained by converting the range typed expression in the following way:
exprformda olduğundaexpr1..expr2(atlanabilir) veexpr2expr1türü olduğunda, olarakintyalıtılır.expr1Whenexpris of the formexpr1..expr2(whereexpr2can be omitted) andexpr1has typeint, then it will be emitted asexpr1.exprformda olduğunda^expr1..expr2expr2(atlanabilir) olarak yalıtılır.receiver.Length - expr1Whenexpris of the form^expr1..expr2(whereexpr2can be omitted), then it will be emitted asreceiver.Length - expr1.exprformda olduğunda..expr2expr2(atlanabilir) olarak yalıtılır.0Whenexpris of the form..expr2(whereexpr2can be omitted), then it will be emitted as0.- Aksi takdirde, olarak
expr.Start.GetOffset(receiver.Length)yayımlar.Otherwise, it will be emitted asexpr.Start.GetOffset(receiver.Length).
Bu değer, ikinci bağımsız değişkenin hesaplanmasında yeniden Slice kullanılır.This value will be re-used in the calculation of the second Slice argument. Bunu yaparken olarak start adlandırılır.When doing so it will be referred to as start. ikinci bağımsız Slice değişkeni, aralık türüne sahip ifade aşağıdaki şekilde dönüştürülerek elde edilir:The second argument of Slice will be obtained by converting the range typed expression in the following way:
exprformda olduğundaexpr1..expr2(atlanabilir) veexpr1expr2türü olduğunda, olarakintyalıtılır.expr2 - startWhenexpris of the formexpr1..expr2(whereexpr1can be omitted) andexpr2has typeint, then it will be emitted asexpr2 - start.exprformda olduğundaexpr1..^expr2expr1(atlanabilir) olarak yalıtılır.(receiver.Length - expr2) - startWhenexpris of the formexpr1..^expr2(whereexpr1can be omitted), then it will be emitted as(receiver.Length - expr2) - start.exprformda olduğundaexpr1..expr1(atlanabilir) olarak yalıtılır.receiver.Length - startWhenexpris of the formexpr1..(whereexpr1can be omitted), then it will be emitted asreceiver.Length - start.- Aksi takdirde, olarak
expr.End.GetOffset(receiver.Length) - startyayımlar.Otherwise, it will be emitted asexpr.End.GetOffset(receiver.Length) - start.
Tüm yan etkilerin yalnızca bir kez yürütülmelerini sağlamak için , receiver Length ve expr ifadeleri uygun şekilde taşacak.The receiver, Length, and expr expressions will be spilled as appropriate to ensure any side effects are only executed once. Örneğin:For example:
class Collection {
private int[] _array = new[] { 1, 2, 3 };
public int Length {
get {
Console.Write("Length ");
return _array.Length;
}
}
public int[] Slice(int start, int length) {
var slice = new int[length];
Array.Copy(_array, start, slice, 0, length);
return slice;
}
}
class SideEffect {
Collection Get() {
Console.Write("Get ");
return new Collection();
}
void Use() {
var array = Get()[0..2];
Console.WriteLine(array.Length);
}
}
Bu kod "Get Length 2" (Uzunluğu Al 2) yazacak.This code will print "Get Length 2".
Dil, aşağıdaki bilinen türler için özel bir durum içerir:The language will special case the following known types:
string:Substringyöntemi yerineSlicekullanılır.string: the methodSubstringwill be used instead ofSlice.array:System.Runtime.CompilerServices.RuntimeHelpers.GetSubArrayyöntemi yerineSlicekullanılır.array: the methodSystem.Runtime.CompilerServices.RuntimeHelpers.GetSubArraywill be used instead ofSlice.
AlternatiflerAlternatives
Yeni işleçler ( ^ ve .. ) ise syntactic şekerdir.The new operators (^ and ..) are syntactic sugar. İşlevsellik, ve fabrika yöntemlerine yapılan açık çağrılar tarafından uygulansa da çok daha ortak koda neden olur ve deneyim uygunsuz System.Index System.Range olur.The functionality can be implemented by explicit calls to System.Index and System.Range factory methods, but it will result in a lot more boilerplate code, and the experience will be unintuitive.
IL GösterimiIL Representation
Bu iki işleç, sonraki derleyici katmanlarında değişiklik olmayacak şekilde normal dizinleyici/yöntem çağrılarına düşürülecek.These two operators will be lowered to regular indexer/method calls, with no change in subsequent compiler layers.
Çalışma zamanı davranışıRuntime behavior
- Derleyici, dizinleyicileri diziler ve dizeler gibi yerleşik türler için en iyi duruma getirmenin ve dizin oluşturmanın uygun mevcut yöntemlere düşürülerek düşürülerek.Compiler can optimize indexers for built-in types like arrays and strings, and lower the indexing to the appropriate existing methods.
System.Indexnegatif bir değerle oluşturulursa oluşturulur.System.Indexwill throw if constructed with a negative value.^0atamaz, ancak sağlanabilir koleksiyonun/numaralanabilirnin uzunluğuna çevrilir.^0does not throw, but it translates to the length of the collection/enumerable it is supplied to.Range.All, ile benzerdir ve0..^0bu dizinler için kod çözme adımlarına sahip olabilir.Range.Allis semantically equivalent to0..^0, and can be deconstructed to these indices.
Dikkat edilmesi gerekenlerConsiderations
ICollection 'e göre dizin algılamayı AlgılaDetect Indexable based on ICollection
Bu davranış için ilham, koleksiyon başlatıcıları idi.The inspiration for this behavior was collection initializers. Bir özelliği kabul etmiş olduğunu iletmek için bir türün yapısını kullanma.Using the structure of a type to convey that it had opted into a feature. Koleksiyon Başlatıcıları türleri söz konusu olduğunda, arabirimi IEnumerable (genel olmayan) uygulayarak özelliği kabul edebilir.In the case of collection initializers types can opt into the feature by implementing the interface IEnumerable (non generic).
Bu teklif başlangıçta, türlerin ICollection dizinlenebilir olarak nitelendirmek için uygulanması gerekir.This proposal initially required that types implement ICollection in order to qualify as Indexable. Bu, birkaç özel durum gerektirse de:That required a number of special cases though:
ref struct: Bu arabirimler,Span<T>Dizin/Aralık desteği için idealdir.ref struct: these cannot implement interfaces yet types likeSpan<T>are ideal for index / range support.string: uygulamazICollectionve bu,interfacebüyük maliyetli bir şekilde eklenemez.string: does not implementICollectionand adding thatinterfacehas a large cost.
Bu, anahtar türlerini desteklemek için özel büyük küçük harfe zaten ihtiyaç duymasıdır.This means to support key types special casing is already needed. Özel büyük küçük harf, string dil olarak diğer alanlarda ( foreach kıs, sabitler, vb.) bunu yaparken daha az ilginç bir değer. Özel büyük küçük harf, ref struct bütün bir tür sınıfına özel olarak büyük küçük harfe göre daha fazla.The special casing of string is less interesting as the language does this in other areas (foreach lowering, constants, etc ...). The special casing of ref struct is more concerning as it's special casing an entire class of types. Yalnızca dönüş türü olan adlı bir özelliğe sahip olmaları halinde dizinlenebilir olarak etiketlenir Count int .They get labeled as Indexable if they simply have a property named Count with a return type of int.
Göz önünde bulundurulduktan sonra, Count / Length bir dönüş türüne sahip bir özelliği olan herhangi bir türün int dizinlenebilir olduğunu varsayalım.After consideration the design was normalized to say that any type which has a property Count / Length with a return type of int is Indexable. Bu, ve dizileri için bile tüm özel büyük harfleri kaldırır string .That removes all special casing, even for string and arrays.
Yalnızca sayıyı AlgılaDetect just Count
Özellik adlarında algılama Count veya Length tasarımın bir bit olduğunu karmaşıklaştırır.Detecting on the property names Count or Length does complicate the design a bit. Çok sayıda tür hariç tutularak, standartlaştırmak için yalnızca bir tane seçilmesi yeterlidir:Picking just one to standardize though is not sufficient as it ends up excluding a large number of types:
- Kullanım
Length: System. Collections ve alt ad alanlarında oldukça çok her koleksiyonu dışlar.UseLength: excludes pretty much every collection in System.Collections and sub-namespaces. Bu, bunlardan türeme eğilimindedirICollectionve bu nedenle uzunluğu tercih ederCount.Those tend to derive fromICollectionand hence preferCountover length. - Kullanım
Count:stringdışama, diziSpan<T>ve enref structtabanlı türlerUseCount: excludesstring, arrays,Span<T>and mostref structbased types
Dizine eklenebilir türlerin ilk algılamasında daha karmaşıkma, diğer yönlerde basitleştirme tarafından belirlenir.The extra complication on the initial detection of Indexable types is outweighed by its simplification in other aspects.
Ad olarak dilim seçimiChoice of Slice as a name
Ad, Slice .net 'teki dilim stili işlemlerine yönelik standart adı olarak seçilmiştir.The name Slice was chosen as it's the de-facto standard name for slice style operations in .NET. Netcoreapp 2.1 'den itibaren tüm yayılma stili türleri, Slice Dilimleme işlemleri için adı kullanır.Starting with netcoreapp2.1 all span style types use the name Slice for slicing operations. Netcoreapp 2.1 'den önce bir örnek için aranacak örneklere örnek yok.Prior to netcoreapp2.1 there really aren't any examples of slicing to look to for an example. Gibi türler List<T> , ArraySegment<T> SortedList<T> Dilimleme için idealdir ancak türler eklendiğinde kavram yoktu.Types like List<T>, ArraySegment<T>, SortedList<T> would've been ideal for slicing but the concept didn't exist when types were added.
Bu nedenle, Slice tek örnek olarak, ad olarak seçilmiştir.Thus, Slice being the sole example, it was chosen as the name.
Dizin hedef türü dönüştürmeIndex target type conversion
Bir Dizin Oluşturucu ifadesinde dönüştürmeyi görüntülemenin bir başka yolu da Index hedef tür dönüştürmesi olarak belirlenir.Another way to view the Index transformation in an indexer expression is as a target type conversion. Bu, formun bir üyesi gibi bağlamak yerine return_type this[Index] , ' a bir hedef türü dönüştürme atar int .Instead of binding as if there is a member of the form return_type this[Index], the language instead assigns a target typed conversion to int.
Bu kavram, countable türlerinde tüm üye erişimlerde genelleştirilemez.This concept could be generalized to all member access on Countable types. Türüne sahip bir ifade bir Index örnek üye çağrısına bağımsız değişken olarak kullanıldığında ve alıcı Countable olduğunda, ifadeye hedef tür dönüştürmesi olur int .Whenever an expression with type Index is used as an argument to an instance member invocation and the receiver is Countable then the expression will have a target type conversion to int. Bu dönüştürmeye uygulanabilecek üye etkinleştirmeleri, Yöntemler, Dizin oluşturucular, özellikler, uzantı yöntemleri vb. içerir. Yalnızca oluşturucular, alıcısı olmadığı için hariç tutulur.The member invocations applicable for this conversion include methods, indexers, properties, extension methods, etc ... Only constructors are excluded as they have no receiver.
Hedef tür dönüştürme, türü olan herhangi bir ifade için aşağıdaki şekilde uygulanır Index .The target type conversion will be implemented as follows for any expression which has a type of Index. Tartışma amaçları için şu örneği kullanın receiver[expr] :For discussion purposes lets use the example of receiver[expr]:
exprBiçimi^expr2ve türü olduğundaexpr2int, öğesine çevrilirreceiver.Length - expr2.Whenexpris of the form^expr2and the type ofexpr2isint, it will be translated toreceiver.Length - expr2.- Aksi takdirde, olarak çevrilir
expr.GetOffset(receiver.Length).Otherwise, it will be translated asexpr.GetOffset(receiver.Length).
receiver Length Yan etkilerin yalnızca bir kez yürütüldüğünden emin olmak için, ve ifadeleri uygun şekilde taşacaktır.The receiver and Length expressions will be spilled as appropriate to ensure any side effects are only executed once. Örneğin:For example:
class Collection {
private int[] _array = new[] { 1, 2, 3 };
public int Length {
get {
Console.Write("Length ");
return _array.Length;
}
}
public int GetAt(int index) => _array[index];
}
class SideEffect {
Collection Get() {
Console.Write("Get ");
return new Collection();
}
void Use() {
int i = Get().GetAt(^1);
Console.WriteLine(i);
}
}
Bu kod "Get length 3" olarak yazdırılır.This code will print "Get Length 3".
Bu özellik, bir dizini temsil eden bir parametreye sahip olan herhangi bir üyeye faydalı olabilir.This feature would be beneficial to any member which had a parameter that represented an index. Örneğin, List<T>.InsertAt.For example List<T>.InsertAt. Ayrıca, bir ifadenin dizin oluşturmak için tasarlanmış olup olmadığı konusunda hiçbir rehberlik veremediğinden, bu da karışıklığın potansiyelini de sağlar.This also has the potential for confusion as the language can't give any guidance as to whether or not an expression is meant for indexing. Tüm bu tür bir deyimi, bir Index int Countable türünde üye çağırırken öğesine dönüştürür.All it can do is convert any Index expression to int when invoking a member on a Countable type.
LarındanRestrictions:
- Bu dönüştürme yalnızca, türündeki ifade
Indexdoğrudan üyenin bir bağımsız değişkeni olduğunda geçerlidir.This conversion is only applicable when the expression with typeIndexis directly an argument to the member. Herhangi bir iç içe geçmiş ifadeye uygulanmaz.It would not apply to any nested expressions.
Uygulama sırasında yapılan kararlarDecisions made during implementation
- Düzendeki tüm Üyeler örnek üye olmalıdırAll members in the pattern must be instance members
- Bir uzunluk yöntemi bulunursa ancak dönüş türü yanlış ise, sayı aramaya devam edinIf a Length method is found but it has the wrong return type, continue looking for Count
- Dizin deseninin kullandığı dizin oluşturucunun tam olarak bir int parametresi olmalıdırThe indexer used for the Index pattern must have exactly one int parameter
- Aralık deseninin kullandığı dilim yöntemi tam olarak iki int parametreye sahip olmalıdırThe Slice method used for the Range pattern must have exactly two int parameters
- Model üyelerini ararken, oluşturulan üyeleri değil, özgün tanımları aradıkWhen looking for the pattern members, we look for original definitions, not constructed members