다음을 통해 공유


18 확장 인덱싱 및 조각화

18.1 일반

이 절에서는 다음과 같이 확장된 인덱싱 가능조각화 가능한컬렉션 형식에 대한 모델을 소개합니다.

  • 이 절 System.Index 에 도입된 형식(§18.2) 및 System.Range (§18.3);
  • 미리 정의된 단항 ^ (§12.9.6) 및 이진 .. (§12.10) 연산자 및
  • element_access 식입니다.

모델에서 형식은 다음과 같이 분류됩니다.

  • 컬렉션요소그룹을 나타내는 경우
  • 값 또는 참조로 형식의 단일 요소를 반환 및/또는 설정하는 형식 의 단일 인수 식이 있는 element_access 식을 지원하는 경우 Index 컬렉션입니다.
  • 값으로 형식 요소의 조각을 반환하는 형식 의 단일 인수 식이 있는 Range 식을 지원하는 경우 확장된 조각화 가능한 컬렉션입니다.

참고: 모델에는 형식의 조각을 설정할 필요가 없지만 형식은 모델의 확장으로 지원할 수 있습니다. 끝 메모

모델은 1차원 배열(§12.8.12.2) 및 문자열(§12.8.12.3)에 대해 지원됩니다.

모델은 모델 의미 체계를 구현하는 적절한 인덱서(§15.9)를 제공하는 모든 클래스, 구조체 또는 인터페이스 형식에서 지원될 수 있습니다.

모델에 대한 암시적 지원은 모델을 직접 지원하지 않지만 특정 멤버 패턴 (§18.4)을 제공하는 형식에 대해 제공됩니다. 이 지원은 의미 체계 기반이 아니라 패턴 기반이며, 해당 형식 멤버의 의미 체계를 기반으로 하는 형식 멤버의 의미 체계는 언어가 이러한 형식 멤버의 의미 체계를 적용하거나 확인하지 않습니다.

이 절의 목적을 위해 다음 용어가 정의됩니다.

  • 컬렉션요소의 그룹을 나타내는 형식입니다.
  • countable 컬렉션셀 수 있는 속성int에 현재 그룹에 있는 요소 수 값이 있는 값이 있는 인스턴스 속성을 제공하는 컬렉션입니다. 이 속성의 이름은 다음 중 하나 Length 또는 Count.로 지정되어야 합니다. 둘 다 있는 경우 전자가 선택됩니다.
  • 시퀀스 또는 인덱싱 가능한 형식은 컬렉션입니다.
    • 개수입니다.
    • 단일 필수 인수가 있는 int 식을 사용하여 모든 요소에 액세스할 수 있는 경우 시작부터 인덱스, 추가 선택적 인수가 허용됩니다.
    • 모든 요소를 element_access 식을 사용하여 설정할 수 있는 경우 시퀀스를 수정할 수 있습니다.
    • 요소의 시작 시작 인덱스는 N 요소가 포함된 시퀀스의 시퀀스에서 요소 앞에 있는 요소의 수입니다.
      • 첫 번째 요소와 마지막 요소에는 각각 0과 N-1의 인덱스가 있으며,
      • 마지막 요소 뒤의 가상 요소를 나타내는 인덱스인 past-end 인덱스에는 값 N이 있습니다.
  • from-end 인덱스는 과거 끝 인덱스를 기준으로 시퀀스 내에서 요소의 위치를 나타냅니다. N 요소가 포함된 시퀀스의 경우 첫 번째, 마지막 및 마지막 끝 인덱스는 각각 N, 1 및 0입니다.
  • 범위는 시퀀스 내의 인덱스에서 시작하는 0개 이상의 인덱스의 연속 실행입니다.
  • 조각은 범위 내의 요소 컬렉션입니다.
  • 조각화 가능한 컬렉션은 다음과 같습니다.
    • 개수입니다.
    • 는 범위를 지정하는 두 개의 Slice 매개 변수를 각각 시작 인덱스와 요소 개수로 사용하고 범위의 요소에서 생성된 새 조각을 반환하는 메서드 int 를 제공합니다.

위의 정의는 다음과 같은 용도 IndexRange 로 확장됩니다.

  • 형식은 인수가 아닌 단일 필수 인수를 사용하는 Index 식이 지원되는 경우에도 int입니다. 구분이 필요한 경우 형식을 확장 인덱싱 가능이라고 합니다.
  • 메서드가 아닌 단일 필수 인수를 사용하는 element_access 식이 지원되는 경우에도 형식을 RangeSlice 있습니다. 구분이 필요한 경우 형식을 확장 슬라이스 가능이라고 합니다.

형식이 countable, indexable 또는 sliceable로 분류되는지 여부는 멤버 접근성(§7.5)의 제약 조건이 적용되므로 형식이 사용되는 위치에 따라 달라집니다.

: countable 속성 및/또는 인덱서가 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 조각화할 수 있으며 시퀀스입니다.

예제 종료

Note:

  • (액세스 가능한) 인덱서가 없기 때문에 인덱싱할 수 없으면 형식을 조각화할 수 있습니다.
  • 형식을 조각화 가능 및/또는 인덱싱할 수 있도록 하려면 형식을 계산할 수 있어야 합니다.
  • 시퀀스의 요소는 시퀀스 내의 위치 별로 정렬되지만 요소 자체는 해당 값으로 정렬되거나 순서가 지정될 필요가 없습니다.

끝 메모

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지정하고 오프셋이 끝() 또는 시작(booltrue)에서 온 것인지를 나타내는 값에서 생성false됩니다. 지정된 오프셋이 음 ArgumentOutOfRangeException 수이면 throw됩니다.

예시

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. 값이 IndexIfrom-end이면 이 메서드는 동일한 값을 length - I.Value반환하고, 그렇지 않으면 동일한 값을 I.Value반환합니다.

메서드는 반환 값이 유효한 범위 0 부터 포함까지 length-1 인지 확인하지 않습니다.

메모: 결과가 요소와 함께 length 시퀀스로 인덱싱되고 인덱싱 작업이 적절한 검사를 수행할 것으로 예상되므로 확인이 지정되지 않습니다. 끝 메모

Index IEquatable<Index> 는 추상 값을 기준으로 같음으로 값을 비교할 수 있습니다. 두 Index 값은 해당 Value 값과 IsFromEnd 속성이 같은 경우에만 동일합니다. 그러나 Index 값은 정렬되지 않으며 다른 비교 작업은 제공되지 않습니다.

메모:Index 값은 추상 인덱스이므로 순서가 지정되지 않습니다. 일반적으로 시퀀스 길이에 대한 참조 없이 시작 인덱스 앞이나 후에 시작 인덱스가 오는지 여부를 확인할 수 없습니다. 콘크리트 인덱스(예: GetOffset콘크리트 인덱스)로 변환되면 이러한 콘크리트 인덱스는 비교할 수 있습니다. 끝 메모

Index값은 다음과 같은 element_access 식(§12.8.12)의 argument_list 직접 사용할 수 있습니다.

  • 배열 액세스 및 대상은 1차원 배열(§12.8.12.2);
  • 문자열 액세스(§12.8.12.3)
  • 인덱서 액세스 및 대상 형식에는 형식(Index) 또는 값을 암시적으로 변환할 수 있는 형식의 해당 매개 변수 가 있는 Index 인덱서가 있습니다.
  • 인덱서 액세스 및 대상 형식은 암시적 Index 지원이 지정된 시퀀스 패턴을 준수합니다(§18.4.2).

18.3 범위 유형

이 형식은 System.Range 인덱스에서 인덱스까지의 Index추상 범위 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설정됩니다.

예시

위의 예제 중 5개는 피연산자의 기본값을 사용하여 단축할 수 있습니다.

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 길이와 관련하여 유효합니다.

  • 속성 Range과 관련하여 구체적인 인덱스는 0에서 Start까지의 End 범위에 있습니다.
  • 의 콘크리트 인덱 Start 스가 다음의 콘크리트 인덱스보다 크지 않습니다. End

인수 GetOffsetAndLength 가 있는 메서드 length 는 추상 Range 값을 튜플로 나타내는 구체적인 Range 값으로 변환합니다. 메서드Rangelength 관련하여 ArgumentOutOfRangeException 유효하지 않은 경우 .

반환된 콘크리트 Range 튜플은 다음과 같은 형식 (S, N) 의 쌍입니다.

  • S 는 범위의 시작 오프셋이며, ;의 속성에 대한 Start 구체적인 인덱스 Range입니다.
  • N 는 범위의 항목 수이며, 구체 인덱스와 EndStart 속성 간의 차이입니다.
  • 두 값 모두에 대해 length계산됩니다.

구체적인 범위 값이 0이면 N 있습니다. 빈 콘크리트 범위는 콘크리트 과거 끝 인덱스 S (§18.1)에 해당하는 값을 가질 수 있으며 비어 있지 않은 범위는 그렇지 않을 수 있습니다. Range 조각(§18.1)에 사용되는 컬렉션이 유효하고 해당 컬렉션과 관련하여 비어 있는 경우 결과 조각은 빈 컬렉션입니다.

메모: 위의 Range 결과는 0과 관련하여 length 유효하고 비어 있는 값을 사용하여 빈 컬렉션을 조각화하고 빈 조각을 생성할 수 있다는 것입니다. 컬렉션이 비어 있는 경우 예외를 throw하는 인덱싱과 다릅니다. 끝 메모*

예시

위에서 정의한 변수를 다음과 함께 사용합니다.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값은 다음과 같은 element_access 식(§12.8.12)의 argument_list 직접 사용할 수 있습니다.

  • 배열 액세스 및 대상은 1차원 배열(§12.8.12.2);
  • 문자열 액세스(§12.8.12.3);
  • 인덱서 액세스 및 대상 형식에는 형식(Range) 또는 값을 암시적으로 변환할 수 있는 형식의 해당 매개 변수 가 있는 Range 인덱서가 있습니다.
  • 인덱서 액세스(§12.8.12.4) 및 대상 형식은 암시적 Range 지원이 지정된 시퀀스 패턴을 준수합니다(§18.4.3).

18.4 인덱스 및 범위에 대한 패턴 기반 암시적 지원

18.4.1 일반

형식이 있고 암시적으로 변환 가능한 E[A]단일 식인 폼 ETAIndex 식(Range)이 다음과 같이 식별되지 않는 경우:

그런 다음 특정 패턴을 준수하는 경우 T 식에 대한 암시적 지원이 제공됩니다. T 이 패턴을 준수하지 않으면 컴파일 시간 오류가 발생합니다.

18.4.2 암시적 인덱스 지원

어떤 컨텍스트에서든 폼element_access 식(E[A])이고, 형식 E 이 있고 T 암시적으로 변환할 수 A있는 Index 단일 식인 경우; 유효하지 않은 경우(§18.4.1) 같은 컨텍스트에 있는 경우:

  • T 는 액세스 가능한 멤버를 시퀀스 로 한정합니다(§18.1); 그리고
  • E[0] 이 유효하며 시퀀스로 한정 T 되는 동일한 인덱서 사용

그러면 식 E[A] 이 암시적으로 지원됩니다.

그렇지 않으면 이 표준의 구현을 제한하지 않으면 식의 평가 순서는 다음과 같아야 합니다.

  1. E 가 평가됩니다.
  2. A 가 평가됩니다.
  3. 구현에 필요한 경우 계산 가능한 속성 T 이 평가됩니다.
  4. 동일한 컨텍스트에서 사용할 int 기반 인덱서의 T get 또는 set 접근 E[0] 자가 호출됩니다.

18.4.3 암시적 범위 지원

어떤 컨텍스트에서든 폼element_access 식(E[A])이고, 형식 E 이 있고 T 암시적으로 변환할 수 A있는 Range 단일 식인 경우; 유효하지 않은 경우(§18.4.1) 같은 컨텍스트에 있는 경우:

  • T는 액세스 가능한 멤버를 개수조각화 가능으로 한정합니다(§18.1).

그러면 식 E[A] 이 암시적으로 지원됩니다.

그렇지 않으면 이 표준의 구현을 제한하지 않으면 식의 평가 순서는 다음과 같아야 합니다.

  1. E 가 평가됩니다.
  2. A 가 평가됩니다.
  3. 구현에 필요한 경우 계산 가능한 속성 T 이 평가됩니다.
  4. 메서드 SliceT 호출됩니다.