Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
18.1 Generalidades
Esta cláusula introduz um modelo para tipos de coleçãoindexáveis e fatiáveis estendidos baseados em:
- Os tipos introduzidos nesta cláusula
System.Index(§18.2) eSystem.Range(§18.3); - Os operadores unários
^(§12.9.6) e binários..(§12.10) predefinidos; - O element_access expressão.
No modelo, um tipo é classificado como:
- uma coleção se representar um grupo de elementoss
- uma coleção indexável estendida se suportar 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, seja por valor ou por referência; - Uma coleção fatiável estendida se ela 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.
Nota: O modelo não requer que uma fatia do tipo possa ser definida, mas um tipo pode suportá-lo como uma extensão do modelo. Nota final
O modelo é suportado para matrizes unidimensionais (§12.8.12.2) e strings (§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 apoio implícito ao modelo é fornecido para tipos que não o apoiam diretamente, mas que fornecem um determinado padrão de membros (§18.4). Esse suporte é baseado em padrões, em vez de baseado em semântica, pois a semântica dos membros do tipo nos quais ele se baseia é assumida – a linguagem não impõe, ou verifica, a semântica desses membros do tipo.
Para efeitos da presente cláusula, entende-se por:
- Uma coleção é um tipo que representa um grupo de elementoss.
- Uma coleção contável é aquela que fornece uma propriedade contável , uma
intpropriedade de instância com valor valorizado cujo valor é o número de elementos atualmente no grupo. Esta propriedade deve ser denominadaLengthCountou . O primeiro é escolhido se ambos existirem. - Uma sequência ou tipo indexável é uma coleção:
- que é contável;
- onde 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 é modificável se cada elemento também puder ser definido usando uma expressão element_access ;
- O índice from-start de um elemento é o número de elementos antes dele na sequência, para uma sequência que contém N elementos:
- o primeiro e o último elementos têm índices de 0 e N-1, respectivamente, e
- o índice passado-final, um índice que representa um elemento hipotético após o último, tem o valor N.
- Um índice from-end representa a posição de um elemento dentro de uma sequência relativa ao índice passado-final. Para uma sequência que contém elementos N , o primeiro, o último e o índice passado-final são N, 1 e 0, respectivamente.
- Um intervalo é uma série contígua de zero ou mais índices que começam em qualquer índice dentro de uma sequência.
- Uma fatia é a coleção de elementos dentro de um intervalo.
- Uma coleção fatiá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 alargadas às utilizações de Index e Range do seguinte modo:
- Um tipo também é uma sequência se uma expressão element_access usando um único argumento necessário
Index, em vez de umintargumento, for suportada. Quando é necessária uma distinção, o tipo é denominado indexável alargado. - Um tipo também é fatiável se uma expressão element_access usando um único argumento necessário
Range, em vez de umSlicemétodo, for suportada. Quando é necessária uma distinção, o tipo é denominado fatiável alargado.
Se um tipo é classificado como contável, indexável ou fatiável está sujeito às restrições de acessibilidade do membro (§7.5) e, portanto, depende de onde o tipo está sendo usado.
Exemplo: Um tipo onde a propriedade contável e/ou o indexador são
protectedé apenas uma sequência para membros de si mesmo e quaisquer tipos derivados. Exemplo final
Os membros necessários para que um tipo se qualifique como uma sequência ou fatiável podem ser herdados.
Exemplo: No seguinte código
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é fatiável e uma sequência.Exemplo final
Observação:
- Um tipo pode ser fatiado sem ser indexável devido à falta de um indexador (acessível).
- Para que um tipo seja fatiável e/ou indexável é necessário que o tipo seja contável.
- Enquanto os elementos de uma sequência são ordenados por posição dentro da sequência, os elementos em si não precisam ser ordenados pelo seu valor, ou mesmo ordenáveis.
Nota final
18.2 O tipo de índice
O System.Index tipo representa um índice abstrato que representa ou um índice inicial ou um índice do fim.
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á lançado.
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 ArgumentOutOfRangeExceptionExemplo final
Há uma conversão implícita a int partir da qual produz índices a partir do Index início, e um operador ^ unário definido pela linguagem (§12.9.6) a int partir do Index qual produz índices a partir do fim.
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 indexExemplo final
O método GetOffset converte de um valor abstrato Index para um valor de índice concreto int para uma sequência do especificado length. Se o Index valor, , for de-end, esse método retornará o mesmo valor que I, caso contrário, length - I.Valueele retornará o mesmo valor que I.Value.
Este método não verifica se o valor de retorno está no intervalo válido de 0 through length-1 inclusive.
Observação: Nenhuma verificação é especificada, pois o uso esperado do resultado é indexar em uma sequência com
lengthelementos, e essa operação de indexação deve executar 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 os respetivos Value e IsFromEnd propriedades forem iguais.
Index No entanto, os valores não são ordenados e nenhuma outra operação de comparação é fornecida.
Observação:
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, por exemplo, porGetOffset, esses índices concretos são comparáveis. Nota final
Index Os valores podem ser utilizados diretamente na argument_list de uma expressão element_access (§12.8.12) que seja:
- um acesso à matriz e o alvo é uma matriz unidimensional (§12.8.12.2);
- um acesso à cadeia de caracteres (§12.8.12.3)
- um acesso 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 convertíveis; - Um acesso indexador e o tipo de destino estão em conformidade com um padrão de sequência para o qual é especificado suporte implícito
Index(§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`Exemplo final
O operador .. definido pela linguagem (§12.10) cria um Range valor a partir de Index valores.
Exemplo
Usando o operador,
..os exemplos acima podem ser escritos: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`Exemplo final
Os operandos de .. são opcionais, o primeiro padrão para 0, o segundo padrão para ^0.
Exemplo
Cinco dos exemplos acima podem ser encurtados confiando em 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`Exemplo final
Um Range valor é válido em relação a um comprimento L se:
- os índices de concreto em relação a L das
RangepropriedadesStarteEndestão na faixa de 0 a L; - o índice de betão para
Startnão é superior ao índice de betão paraEnd
O método GetOffsetAndLength com um argumento length converte um valor abstrato Range em um valor concreto Range representado por tupla. Se o Range não é válido em relação ao length método lança ArgumentOutOfRangeException.
A tupla de concreto Range devolvido é um par da forma (S, N) onde:
-
Sé o deslocamento inicial do intervalo, sendo o índice concreto para aStartpropriedade doRange; -
Né o número de itens no intervalo, sendo a diferença entre os índices concretos para oEndeStartpropriedades; - sendo ambos os valores calculados em relação a
length.
Um valor de intervalo concreto está vazio se N for zero. Um intervalo de betão vazio pode ter um S valor igual ao índice passado-final do betão (§18.1), um intervalo não vazio não pode. Quando uma Range coleção que é usada para fatiar (§18.1) uma coleção é válida e vazia em relação a essa coleção, então a fatia resultante é uma coleção vazia.
Observação: Uma consequência do acima exposto é que um
Rangevalor válido e vazio em relação a umlengthde zero pode ser usado para fatiar uma coleção vazia e resulta em uma fatia vazia. Isso difere da indexação, que lança 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 respetivas Start propriedades e End forem iguais (§18.2).
Range No entanto, os valores não são ordenados e nenhuma outra operação de comparação é fornecida.
Observação:
Rangeos valores não são ordenados, pois são abstratos e não há uma relação de ordenação única. Uma vez convertido em um início e comprimento concretos, por exemplo, porGetOffsetAndLength, uma relação de ordenação pode ser definida. Nota final
Range Os valores podem ser usados diretamente na argument_list de uma expressão element_access (§12.8.12) que é:
- um acesso à matriz e o alvo é uma matriz unidimensional (§12.8.12.2);
- um acesso por cadeia de caracteres (§12.8.12.3);
- um acesso 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 convertíveis; - um acesso indexador (§12.8.12.4) e o tipo de destino está em conformidade com um padrão de sequência para o qual é especificado suporte implícito
Range(§18.4.3).
18.4 Suporte implícito baseado em padrões para índice e intervalo
18.4.1 Generalidades
Se uma expressão element_access (§12.8.12) do formulário E[A]; em que E tem tipo T e A é uma única expressão implicitamente convertível em Index ou Range; não for identificada como:
- um acesso à matriz (§12.8.12.2),
- um acesso de cadeia de caracteres (§12.8.12.3), ou
- um acesso de indexador (§12.8.12.4), uma vez que
Tnão fornece um indexador acessível adequado
em seguida, o suporte implícito para a expressão é fornecido se T estiver em conformidade com um padrão particular. Se T não estiver de acordo com este padrão, ocorrerá um erro em tempo de compilação.
18.4.2 Suporte de índice implícito
Se, em qualquer contexto, uma expressão element_access (§12.8.12) do formulário E[A]; onde E tem tipo T e A é uma única expressão implicitamente convertível em Index; não é válida (§18.4.1), então se no mesmo contexto:
-
Tfornece membros acessíveis qualificando-o como uma sequência (§18.1); e ainda - A expressão
E[0]é válida e usa o mesmo indexador que seTqualifica como uma sequência
nesse caso, a expressão E[A] deve ser implicitamente apoiada.
Sem restringir de outra forma as implementações desta Norma, a ordem de avaliação da expressão será equivalente a:
-
Eé avaliado; -
Aé avaliado; - a propriedade contável de
Té avaliada, se exigido pela implementação; - O acessador get ou set do
intindexadorTbaseado que seria usado porE[0]no mesmo contexto é invocado.
18.4.3 Suporte implícito de intervalo
Se, em qualquer contexto, uma expressão element_access (§12.8.12) do formulário E[A]; onde E tem tipo T e A é uma única expressão implicitamente convertível em Range; não é válida (§18.4.1), então se no mesmo contexto:
-
Tfornece membros acessíveis qualificando-o como contável e fatiável (§18.1)
nesse caso, a expressão E[A] deve ser implicitamente apoiada.
Sem restringir de outra forma as implementações desta Norma, a ordem de avaliação da expressão será equivalente a:
-
Eé avaliado; -
Aé avaliado; - a propriedade contável de
Té avaliada, se exigido pela implementação; - o
Slicemétodo de é invocadoT.
ECMA C# draft specification