Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
18.1 Общие
В этом предложении представлена модель для расширенных индексируемых и срезаемых типов коллекций, созданных на основе:
- Типы, представленные в этом предложении,
System.Index(§18.2) иSystem.Range(§18.3); - Предопределенные унарные
^операторы (§12.9.6) и двоичные..(§12.10) и - Выражение element_access .
В модели тип классифицируется следующим образом:
- Коллекция, если она представляет группу элементов
-
расширенная индексируемая коллекция, если она поддерживает выражение element_access, которое имеет одно выражение аргумента типа, которое возвращает и/или задает один элемент типа
Index, по значению или по ссылке; -
Расширенная срезаемая коллекция, если она поддерживает выражение element_access, которое имеет одно выражение аргумента типа
Range, которое возвращает срез элементов типа по значению.
Примечание. Модель не требует установки среза типа, но тип может поддерживать его как расширение модели. конечная заметка
Модель поддерживается для одномерных массивов (§12.8.12.2) и строк (§12.8.12.3).
Модель может поддерживаться любым классом, структурой или типом интерфейса, который предоставляет соответствующие индексаторы (§15.9), реализующие семантику модели.
Неявная поддержка модели предоставляется для типов, которые не поддерживают его напрямую, но предоставляют определенный шаблон элементов (§18.4). Эта поддержка основана на шаблонах, а не на основе семантики, так как семантика элементов типа, на которых она основана, — язык не применяется или проверяет семантику этих элементов типа.
В целях этого предложения определены следующие термины:
- Коллекция — это тип, представляющий группу элементов.
-
Подсчитываемая коллекция — это коллекция, которая предоставляет подсчитываемое свойство экземпляра с
intзначением, значение которого — это количество элементов, которые в настоящее время находятся в группе. Это свойство должно быть названо либоLengthилиCount. Первый выбирается, если оба существуют. -
Последовательность или индексируемый тип — это коллекция:
- значение, которое можно подсчитать;
- где доступ к каждому элементу можно получить с помощью выражения element_access с одним обязательным
intаргументом, индексом от начала разрешены дополнительные необязательные аргументы; - последовательность модификируется , если каждый элемент также можно задать с помощью выражения element_access ;
- Индекс от начала элемента — это число элементов перед ним в последовательности для последовательности, содержащей N-элементы :
- первые и последние элементы имеют индексы 0 и N-1 соответственно, и
- прошлый индекс, индекс, представляющий гипотетический элемент после последнего, имеет значение N.
- Индекс из конца представляет позицию элемента в последовательности относительно последнего индекса. Для последовательности, содержащей N-элементы , первые, последние и конечные индексы: N, 1 и 0 соответственно.
- Диапазон представляет собой последовательный запуск нулевых или более индексов, начиная с любого индекса в последовательности.
- Срез — это коллекция элементов в диапазоне.
-
Срезная коллекция — это одна из следующих элементов:
- имеет значение countable;
- предоставляет метод
Slice, который принимает дваintпараметра, указывающие диапазон, будучи начальным индексом и числом элементов соответственно, и возвращает новый срез, созданный из элементов в диапазоне.
Приведенные выше определения расширены для использования Index и Range следующим образом:
- Тип также является последовательностью , если выражение element_access принимает один обязательный
Indexаргумент, а неintаргумент, поддерживается. Если требуется различие, тип называется расширенным индексируемым. - Тип также можно срезать , если выражение element_access принимает один обязательный
Rangeаргумент, а неSliceметод. Если требуется различие, тип называется расширенным срезом.
Классифицируется ли тип как подсчитываемый, индексируемый или срез, зависит от ограничений специальных возможностей членов (§7.5) и, следовательно, зависит от того, где используется тип.
Пример. Тип, в котором вычисляемое свойство и /или индексатор является
protectedтолько последовательностью для членов себя и любых производных типов. заключительный пример
Обязательные элементы для типа, квалифицируемые как последовательность или срез, могут быть унаследованы.
пример: в следующем коде
public class A { public int Length { get { … } } } public class B : A { public int this(int index) { … } } public class C : B { public int[] Slice(int index, int count) { … } }Тип
Aподсчитывается,Bявляется последовательностью иCсрезом и последовательностью.заключительный пример
Примечание.
- Тип может быть срезан без индексации из-за отсутствия (доступного) индексатора.
- Чтобы тип был срезаемым и (или) индексируемым, требуется, чтобы тип был подсчитываемым.
- Хотя элементы последовательности упорядочены по позиции в последовательности, сами элементы не должны быть упорядочены по их значению или даже упорядоченным.
конечная заметка
18.2 Тип индекса
Тип System.Index представляет абстрактный индекс, представляющий либо индекс из начала, либо индекс из конца.
public readonly struct Index : IEquatable<Index>
{
public int Value { get; }
public bool IsFromEnd { get; }
public Index(int value, bool fromEnd = false);
public static implicit operator Index(int value);
public int GetOffset(int length);
public bool Equals(Index other);
}
Index значения создаются из int, указывая не отрицательное смещение и boolзначение, указывающее, является ли смещение от конца (true) или запуска (false). Если указанное смещение является отрицательным ArgumentOutOfRangeException , создается.
Пример
Index first = new Index(0, false); // first element index var last = new Index(1, true); // last element index var past = new Index(0, true); // past-end index Index invalid = new Index(-1); // throws ArgumentOutOfRangeExceptionзаключительный пример
Существует неявное преобразование, intIndex из которого производится от начала индексов, и определяемый языком унарный оператор ^ (§12.9.6), из intIndex которого производится из конечных индексов.
Пример
С помощью неявных преобразований и унарного
^оператора, приведенных выше, можно записать:Index first = 0; // first element index var last = ^1; // last element index var past = ^0; // past-end indexзаключительный пример
Метод GetOffset преобразуется из абстрактного Index значения в конкретное int значение индекса для последовательности указанного значения length. Если значение, Indexто в I конце этого метода возвращается то же значение, что и в противном случае возвращается то же значение, что length - I.ValueI.Valueи .
Этот метод не проверяет, находится ли возвращаемое значение в допустимом диапазоне 0 включительно length-1 .
Заметка: Проверка не указана, так как ожидаемое использование результата заключается в индексировании в последовательности с
lengthэлементами, и эта операция индексирования, как ожидается, выполняет соответствующие проверки. конечная заметка
Index
IEquatable<Index> реализации и значения можно сравнить для равенства на основе абстрактного значения; два Index значения равны, если соответствующие Value и IsFromEnd свойства равны. Однако Index значения не упорядочены и другие операции сравнения не предоставляются.
Заметка:
IndexЗначения не упорядочены по мере того, как они являются абстрактными индексами, обычно невозможно определить, приходит ли индекс из конца до или после начального индекса без ссылки на длину последовательности. После преобразования в конкретные индексы, например,GetOffsetэти конкретные индексы сопоставимы. конечная заметка
Index значения могут использоваться непосредственно в argument_list выражения element_access (§12.8.12), т. е.
- доступ к массиву и целевой объект является одномерным массивом (§12.8.12.2);
- строковый доступ (§12.8.12.3)
- доступ индексатора и целевой тип имеет индексатор с соответствующими параметрами любого
Indexтипа (§12.8.12.4) или типа, к которомуIndexзначения неявно преобразуются; или - доступ индексатора и целевой тип соответствуют шаблону последовательности, для которой указана неявная
Indexподдержка (§18.4.2).
18.3 Тип диапазона
Тип System.Range представляет абстрактный диапазон Indexes от Start индекса до индекса, но не включая End индекс.
public readonly struct Range : IEquatable<Index>
{
public Index Start { get; }
public Index End { get; }
public Range(Index start, Index end);
public (int Offset, int Length) GetOffsetAndLength(int length);
public bool Equals(Range other);
}
Range значения создаются из двух Index значений.
Пример
В следующих примерах используется неявное преобразование из
intIndex(§18.2) и^оператор (§12.9.6) для созданияIndexзначений для каждогоRange:var firstQuad = new Range(0, 4); // the indices from `0` to `3` // int values impicitly convert to `Index` var nextQuad = new Range(4, 8); // the indices from `4` to `7` var wholeSeq = new Range(0, ^0); // the indices from `0` to `N-1` where `N` is the // length of the sequence wholeSeq is used with var dropFirst = new Range(1, ^0); // the indices from `1` to `N-1` var dropLast = new Range(0, ^1); // the indices from `0` to `N-2` var maybeLast = new Range(^1, 6); // the indices from `N-1` to 5 var lastTwo = new Range(^2, ^0); // the indices from `N-2` to `N-1`заключительный пример
Определяемый языком оператор .. (§12.10) создает Range значение из Index значений.
Пример
С помощью оператора, приведенного
..выше, можно написать следующее:var firstQuad = 0..4; // the indices from `0` to `3` var nextQuad = 4..8; // the indices from `4` to `7` var wholeSeq = 0..^0; // the indices from `0` to `N-1` var dropFirst = 1..^0; // the indices from `1` to `N-1` var dropLast = 0..^1; // the indices from `0` to `N-2` var maybeLast = ^1..6; // the indices from `N-1` to 5 var lastTwo = ^2..^0; // the indices from `N-2` to `N-1`заключительный пример
Операнды .. являются необязательными, первые значения по умолчанию используются по умолчанию0^0.
Пример
Пять из приведенных выше примеров можно сократить, опираясь на значения по умолчанию для операндов:
var firstQuad = ..4; // the indices from `0` to `3` var wholeSeq = ..; // the indices from `0` to `N-1` var dropFirst = 1..; // the indices from `1` to `N-1` var dropLast = ..^1; // the indices from `0` to `N-2` var lastTwo = ^2..; // the indices from `N-2` to `N-1`заключительный пример
Значение Rangeдопустимо в отношении длины L , если:
- конкретные индексы относительно L
RangeсвойствStartиEndнаходятся в диапазоне от 0 до L; и - конкретный индекс не превышает конкретный индекс
StartдляEnd
Метод GetOffsetAndLength с аргументом length преобразует абстрактное Range значение в конкретное Range значение, представленное кортежем. Если недопустимый Rangelength метод вызывает ArgumentOutOfRangeExceptionисключение.
Возвращаемый бетонный Range кортеж является парой формы (S, N) , в которой:
-
S— начальное смещение диапазона, являясь конкретным индексом дляStartсвойства объектаRange; и -
N— это количество элементов в диапазоне, то есть разница между конкретными индексами дляEndиStartсвойств; - оба значения вычисляются относительно
length.
Значение конкретного диапазона пусто , если N равно нулю. Пустой S диапазон бетона может иметь значение, равное конкретному индексу в прошлом (§18.1), непустый диапазон может не совпадать. Когда коллекция Range используется для среза (§18.1) является допустимой и пустой в отношении этой коллекции, то результирующий срез является пустой коллекцией.
Заметка: Следствием приведенного выше является то, что
Rangeдопустимое и пустое значение в отношенииlengthнуля может использоваться для среза пустой коллекции и приводит к пустому срезу. Это отличается от индексирования, которое создает исключение, если коллекция пуста. конечная заметка*
Пример
Использование переменных, определенных выше, с
GetOffSetAndLength(6):var (ix0, len0) = firstQuad.GetOffsetAndLength(6); // ix0 = 0, len0 = 4 var (ix1, len1) = nextQuad.GetOffsetAndLength(6); // throws // ArgumentOutOfRangeException as range crosses sequence end var (ix2, len2) = wholeSeq.GetOffsetAndLength(6); // ix2 = 0, len2 = 6 var (ix3, len3) = dropFirst.GetOffsetAndLength(6); // ix3 = 1, len3 = 5 var (ix4, len4) = dropLast.GetOffsetAndLength(6); // ix4 = 0, len4 = 5 var (ix5, len5) = maybeLast.GetOffsetAndLength(6); // ix5 = 5, len5 = 1 var (ix6, len6) = lastTwo.GetOffsetAndLength(6); // ix6 = 4, len6 = 2
Range
IEquatable<Range> реализации и значения можно сравнить для равенства на основе абстрактного значения; два Range значения равны, если абстрактные значения соответствующих Start и End свойств равны (§18.2). Однако Range значения не упорядочены и другие операции сравнения не предоставляются.
Заметка:
Rangeзначения не упорядочены как абстрактные, так и нет уникального отношения упорядочивания. После преобразования в бетонное начало и длину, напримерGetOffsetAndLengthпутем упорядочения, можно определить отношение упорядочения. конечная заметка
Range значения можно использовать непосредственно в argument_list выражения element_access (§12.8.12), которое:
- доступ к массиву и целевой объект является одномерным массивом (§12.8.12.2);
- строковый доступ (§12.8.12.3);
- доступ индексатора и целевой тип имеет индексатор с соответствующими параметрами любого
Rangeтипа (§12.8.12.4) или типа, к которомуRangeзначения неявно преобразуются; или - доступ индексатора (§12.8.12.4) и целевой тип соответствует шаблону последовательности, для которой указана неявная
Rangeподдержка (§18.4.3).
Неявная поддержка индексов и диапазонов на основе шаблонов 18.4
18.4.1 Общие
Если выражение element_access (§12.8.12) формы E[A], где E имеет тип T и A является неявным Index преобразованием одного выражения в или Range; не удается определить как:
- доступ к массиву (§12.8.12.2),
- строковый доступ (§12.8.12.3) или
- доступ индексатора (§12.8.12.4), так как
Tне предоставляет подходящий индексатор.
Затем неявная поддержка выражения предоставляется, если T соответствует определенному шаблону. Если T этот шаблон не соответствует этому шаблону, возникает ошибка во время компиляции.
Поддержка неявного индекса 18.4.2
Если в любом контексте выражение element_access (§12.8.12) формы E[A]; где E имеет тип T и A является неявным преобразуемым Indexвыражением; недопустимо (§18.4.1), то в том же контексте:
-
Tпредоставляет доступные члены, квалифицируя его как последовательность (§18.1); и - Выражение
E[0]допустимо и использует тот же индексатор, который квалифифисируетсяTкак последовательность
затем выражение E[A] должно быть неявно поддерживается.
Без ограничения реализаций этого стандарта порядок оценки выражения должен быть эквивалентен следующим:
-
Eвычисляется; -
Aвычисляется; - вычисляемое число свойств
T, если требуется реализацией; - Вызывается метод доступа к индексатору
intTна основе объекта get или set, который будет использоватьсяE[0]в том же контексте.
Поддержка неявного диапазона 18.4.3
Если в любом контексте выражение element_access (§12.8.12) формы E[A]; где E имеет тип T и A является неявным преобразуемым Rangeвыражением; недопустимо (§18.4.1), то в том же контексте:
затем выражение E[A] должно быть неявно поддерживается.
Без ограничения реализаций этого стандарта порядок оценки выражения должен быть эквивалентен следующим:
-
Eвычисляется; -
Aвычисляется; - вычисляемое число свойств
T, если требуется реализацией; -
SliceВызывается методT.
ECMA C# draft specification