Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
18.1 Geral
Esta cláusula introduz um modelo para tipos de coleçãoindexáveis e segmentáveis estendidos baseados em:
- Os tipos introduzidos nesta cláusula,
System.Index(§18.2) eSystem.Range(§18.3); - Os operadores unários
^predefinidos (§12.9.6) e binários..(§12.10) e - A expressão element_access .
No modelo, um tipo é classificado como:
- uma coleção se ela representa um grupo de elementoss
- uma coleção indexável estendida se oferecer suporte a uma expressão element_access que tenha uma única expressão de argumento do tipo
Indexque retorna e/ou define um único elemento do tipo, por valor ou por referência; e - uma coleção segmentável estendida se oferecer suporte a uma expressão element_access que tenha uma única expressão de argumento do tipo
Rangeque retorna uma fatia dos elementos do tipo por valor.
Observação: o modelo não exige que uma fatia do tipo possa ser definida, mas um tipo pode dar suporte a ele como uma extensão do modelo. nota final
O modelo tem suporte para matrizes unidimensionais (§12.8.12.2) e cadeias de caracteres (§12.8.12.3).
O modelo pode ser suportado por qualquer classe, struct ou tipo de interface que forneça indexadores apropriados (§15.9) que implementem a semântica do modelo.
O suporte implícito para o modelo é fornecido para tipos que não dão suporte diretamente a ele, mas que fornecem um determinado padrão de membros (§18.4). Esse suporte é baseado em padrão, em vez de baseado em semântica, como a semântica dos membros do tipo nos quais se baseia são assumidas – o idioma não impõe ou verifica a semântica desses membros de tipo.
Para os fins desta cláusula, os seguintes termos são definidos:
- Uma coleção é um tipo que representa um grupo de elementos.
- Uma coleção que pode ser contada é aquela que fornece uma propriedade de instância cujo valor é o número de elementos atualmente no grupo. Essa propriedade deve ser nomeada
LengthouCount. O primeiro será escolhido se ambos existirem. - Uma sequência ou tipo indexável é uma coleção:
- que é contível;
- em que cada elemento pode ser acessado usando uma expressão element_access com um único argumento necessário
int, o índice de início, argumentos opcionais adicionais são permitidos; - uma sequência será modificável se cada elemento também puder ser definido usando uma expressão element_access ;
- O índice de um elemento desde o início é o número de elementos antes dele na sequência, para uma sequência que contém N elementos:
- os primeiros e últimos elementos têm índices de 0 e N-1, respectivamente, e
- o índice de última extremidade, um índice que representa um elemento hipotético após o último, tem o valor N.
- Um índice de ponta representa a posição de um elemento dentro de uma sequência relativa ao índice de última hora. Para uma sequência que contém N elementos, os índices primeiro, último e último são N, 1 e 0, respectivamente.
- Um intervalo é uma execução contígua de zero ou mais índices começando em qualquer índice dentro de uma sequência.
- Uma fatia é a coleção de elementos dentro de um intervalo.
- Uma coleção segmentável é aquela que:
- é contível;
- fornece um método
Sliceque usa doisintparâmetros especificando um intervalo, sendo um índice inicial e uma contagem de elementos, respectivamente, e retorna uma nova fatia construída a partir dos elementos no intervalo.
As definições acima são estendidas para usos de e Index da Range seguinte maneira:
- Um tipo também será uma sequência se uma expressão element_access que usa um único argumento necessário
Index, em vez de umintargumento, tiver suporte. Quando uma distinção é necessária, o tipo é denominado indexável estendido. - Um tipo também será fatiado se uma expressão element_access que usa um único argumento necessário
Range, em vez de umSlicemétodo, tiver suporte. Quando uma distinção é necessária, o tipo é denominado segmentável estendido.
Se um tipo é classificado como contagem, indexável ou segmentável está sujeito às restrições de acessibilidade de membro (§7,5) e, portanto, dependente de onde o tipo está sendo usado.
Exemplo: um tipo em que a propriedade countable e/ou o indexador são
protectedapenas uma sequência para membros de si mesmo e de qualquer tipo derivado. fim de exemplo
Os membros necessários para um tipo se qualificar como uma sequência ou segmentável podem ser herdados.
Exemplo: no código a seguir
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) { … } }O tipo
Aé contível,Bé uma sequência eCé segmentável e uma sequência.fim de exemplo
Note:
- Um tipo pode ser fatiado sem ser indexável devido à falta de um indexador (acessível).
- Para que um tipo seja segmentável e/ou indexável, é necessário que o tipo seja contível.
- Embora os elementos de uma sequência sejam ordenados por posição dentro da sequência, os próprios elementos não precisam ser ordenados por seu valor ou mesmo orderable.
nota final
18.2 O tipo de índice
O System.Index tipo representa um índice abstrato que representa um índice desde o início ou um índice de ponta.
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 os valores são construídos a partir de um int, especificando o deslocamento não negativo e um bool, indicando se o deslocamento é do final (true) ou do início (false). Se o deslocamento especificado for negativo, um ArgumentOutOfRangeException será gerado.
Exemplo
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 ArgumentOutOfRangeExceptionfim de exemplo
Há uma conversão implícita da intIndex qual produz índices de início e um operador ^ unário definido por linguagem (§12.9.6) para int o Index qual produz índices de ponta.
Exemplo
Usando conversões implícitas e o operador unário
^, os exemplos acima podem ser escritos:Index first = 0; // first element index var last = ^1; // last element index var past = ^0; // past-end indexfim de exemplo
O método GetOffset converte de um valor abstrato Index em um valor de índice concreto int para uma sequência do especificado length. Se o Index valor for I, será de ponta a ponta, esse método retornará o mesmo valor length - I.Valueque, caso contrário, retornará o mesmo valor que I.Value.
Esse método não verifica se o valor retornado está no intervalo válido de por meio 0 da length-1 inclusão.
Nota: Nenhuma verificação é especificada, pois o uso esperado do resultado é indexar em uma sequência com
lengthelementos, e espera-se que a operação de indexação execute as verificações apropriadas. nota final
Index implementos IEquatable<Index> e valores podem ser comparados para igualdade com base no valor abstrato; dois Index valores são iguais se e somente se as respectivas Value propriedades e IsFromEnd propriedades forem iguais. No entanto Index , os valores não são ordenados e nenhuma outra operação de comparação é fornecida.
Nota:
Indexos valores não são ordenados, pois são índices abstratos, em geral é impossível determinar se um índice de ponta vem antes ou depois de um índice de início sem referência a um comprimento de sequência. Uma vez convertidos em índices concretos, porGetOffsetexemplo, esses índices concretos são comparáveis. nota final
Index os valores podem ser usados diretamente no argument_list de uma expressão element_access (§12.8.12), que é:
- um acesso de matriz e o destino é uma matriz unidimensional (§12.8.12.2);
- um acesso de cadeia de caracteres (§12.8.12.3)
- um acesso de indexador e o tipo de destino tem um indexador com parâmetros correspondentes de qualquer
Indextipo (§12.8.12.4) ou de um tipo para o qualIndexos valores são implicitamente conversíveis; ou - um acesso de indexador e o tipo de destino estão em conformidade com um padrão de sequência para o qual o suporte implícito
Indexé especificado (§18.4.2).
18.3 O tipo de intervalo
O System.Range tipo representa o intervalo abstrato de Indexes de um Start índice até, mas não incluindo, um End índice.
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 os valores são construídos a partir de dois Index valores.
Exemplo
Os exemplos a seguir usam a conversão implícita de
intparaIndex(§18.2) e o^operador (§12.9.6) para criar osIndexvalores para cadaRange: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`fim de exemplo
O operador .. definido pelo idioma (§12.10) cria um Range valor a partir de Index valores.
Exemplo
Usando o
..operador, os exemplos acima podem ser gravados: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`fim de exemplo
Os operandos de .. são opcionais, o primeiro usa como padrão 0, o segundo usa como padrão ^0.
Exemplo
Cinco dos exemplos acima podem ser reduzidos dependendo dos valores padrão para operandos:
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`fim de exemplo
Um Range valor é válido em relação a um comprimento L se:
- os índices concretos em relação a L das
RangepropriedadesStarteEndestão no intervalo de 0 a L; e - o índice concreto para
Startnão é maior do que o índice concreto paraEnd
O método GetOffsetAndLength com um argumento length converte um valor abstrato Range em um valor concreto Range representado pela tupla. Se o Range método não for válido em relação ao length método será gerado ArgumentOutOfRangeException.
A tupla de concreto Range retornada é um par da forma (S, N) em que:
-
Sé o deslocamento inicial do intervalo, sendo o índice concreto para aStartpropriedade doRange; e -
Né o número de itens no intervalo, sendo a diferença entre os índices concretos para as propriedades eEndasStartpropriedades; - ambos os valores que estão sendo calculados em relação a
length.
Um valor de intervalo concreto estará vazio se N for zero. Um intervalo de concreto vazio pode ter um S valor igual ao índice de última extremidade concreto (§18.1), um intervalo não vazio pode não ser. Quando um Range que é usado para fatiar (§18.1) uma coleção é válida e vazia em relação a essa coleção, a fatia resultante é uma coleção vazia.
Nota: Uma consequência disso é que um
Rangevalor válido e vazio em relação a umlengthzero pode ser usado para fatiar uma coleção vazia e resultar em uma fatia vazia. Isso difere da indexação que gera uma exceção se a coleção estiver vazia. nota final*
Exemplo
Usando as variáveis definidas acima com
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 implementos IEquatable<Range> e valores podem ser comparados para igualdade com base no valor abstrato; dois Range valores são iguais se e somente se os valores abstratos das respectivas Start propriedades forem End iguais (§18,2). No entanto Range , os valores não são ordenados e nenhuma outra operação de comparação é fornecida.
Nota:
Rangeos valores não são ordenados, pois são abstratos e não há nenhuma relação de ordenação exclusiva. Uma vez convertido em um início e comprimento concretos, por exemplo, umaGetOffsetAndLengthrelação de ordenação poderia ser definida. nota final
Range os valores podem ser usados diretamente no argument_list de uma expressão element_access (§12.8.12), que é:
- um acesso de matriz e o destino é uma matriz unidimensional (§12.8.12.2);
- um acesso de cadeia de caracteres (§12.8.12.3);
- um acesso de indexador e o tipo de destino tem um indexador com parâmetros correspondentes de qualquer
Rangetipo (§12.8.12.4) ou de um tipo para o qualRangeos valores são implicitamente conversíveis; ou - um acesso de indexador (§12.8.12.4) e o tipo de destino está em conformidade com um padrão de sequência para o qual o suporte implícito
Rangeé especificado (§18.4.3).
18.4 Suporte implícito baseado em padrão para Índice e Intervalo
18.4.1 Geral
Se uma expressão element_access (§12.8.12) do formulário E[A]; onde E tem o tipo T e A é uma única expressão implicitamente conversível para Index ou Range; não é identificado como:
- um acesso de matriz (§12.8.12.2),
- um acesso de cadeia de caracteres (§12.8.12.3) ou
- um acesso de indexador (§12.8.12.4) como
Tnão fornece nenhum indexador acessível adequado
em seguida, o suporte implícito para a expressão será fornecido se T estiver em conformidade com um padrão específico. Se T não estiver em conformidade com esse padrão, ocorrerá um erro de tempo de compilação.
Suporte a índice implícito 18.4.2
Se, em qualquer contexto, uma expressão de element_access (§12.8.12) do formulário E[A]; em que E tem o tipo T e A é uma única expressão implicitamente conversível para Index; não é válida (§18.4.1) em seguida, se no mesmo contexto:
-
Tfornece membros acessíveis qualificando-o como uma sequência (§18.1); e - a expressão
E[0]é válida e usa o mesmo indexador que se qualificaTcomo uma sequência
em seguida, a expressão E[A] deve ter suporte implícito.
Sem restringir as implementações deste Padrão, a ordem de avaliação da expressão será equivalente a:
-
Eé avaliado; -
Aé avaliado; - a propriedade countable de
Té avaliada, se necessário pela implementação; - o acessador get ou set do
intindexadorTbaseado do qual seria usadoE[0]no mesmo contexto é invocado.
18.4.3 Suporte a intervalo implícito
Se, em qualquer contexto, uma expressão de element_access (§12.8.12) do formulário E[A]; em que E tem o tipo T e A é uma única expressão implicitamente conversível para Range; não é válida (§18.4.1) em seguida, se no mesmo contexto:
-
Tfornece membros acessíveis qualificando-o como contável e fatiado (§18.1)
em seguida, a expressão E[A] deve ter suporte implícito.
Sem restringir as implementações deste Padrão, a ordem de avaliação da expressão será equivalente a:
-
Eé avaliado; -
Aé avaliado; - a propriedade countable de
Té avaliada, se necessário pela implementação; - o
Slicemétodo deTé invocado.
ECMA C# draft specification