C#

[C# 8.0] System.Index / System.Range / ^(캐럿) 연산자를 사용한 컬렉션 접근

셍송 2024. 6. 25. 18:35


C# 8.0에 추가된 System.Index, System.Range 구조체와 ^, .. 에 대해 정리하였다.

해당 구조체와 연산자를 이용하면 보다 쉽고 편리하게 컬렉션에 접근 및 슬라이싱 할 수 있다.

 

Index

기존 C#에서는 끝에서부터 컬렉션에 접근하고 싶을 때에 주로 길이를 이용해 접근하였다.

var array = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var lastData = array[array.Length - 1]; // 마지막 데이터에 접근

 

^ 은 컬렉션의 끝에서부터 접근할 수 있도록 해주기 때문에, 아래와 같이 간결하게 코드를 작성할 수 있다.

var array = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var lastData = array[^1]; // 마지막 데이터에 접근

단, 0부터 시작하는 인덱스 넘버와는 다르게 ^ 은 1부터 시작하니 주의해야한다!

 

System.Index 에서는 컬렉션에 접근할 방향과 인덱스 넘버 둘 다 저장하여 편리하게 사용할 수 있다.

var array = new int[] { 1, 2, 3, 4, 5, 6, 7 };
Index index1 = ^2; // 뒤에서 두번째 데이터에 접근 ; 6
Index index2 = new Index(2, fromEnd: true); // 생성자를 통해서도 뒤에서 부터 접근 가능한 Index를 만들 수 있다.
Index index3 = new Index(2, fromEnd: false); // fromEnd: false 의 경우 앞에서 부터 접근한다.

// 결과는 같다.
Console.WriteLine(array[index1]); // 6
Console.WriteLine(array[index2]); // 6

// 0부터 시작하여 앞에서 세번째 데이터에 접근
Console.WriteLine(array[index3]); // 3

// GetOffset 함수에 해당 컬렉션의 길이를 넣고 호출시 실제 인덱스 넘버(앞에서 부터 센)를 알 수 있다.
Console.WriteLine(index1.GetOffset(array.Length)); // 5
Console.WriteLine(index2.GetOffset(array.Length)); // 5
Console.WriteLine(index3.GetOffset(array.Length)); // 2

 

 

Range

System.Range 와 .. 를 이용하면 시작 인덱스 값과 끝 인덱스 값 통해 컬렉션의 범위를 나타낼 수 있다.

..를 사용한 예제는 아래와 같다.

var array = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var slice = array[0..5]; 

foreach (var v in slice)
{
    Console.WriteLine(v); // 1,2,3,4,5
}

이때, 끝 인덱스 값은 포함하지 않고 끝 인덱스 값 -1 까지만 슬라이스하기 때문에 주의해야한다!

 

아래와 같이 사용도 가능하다.

var slice1 = array[..5]; // 시작값 생략 가능. 0..5와 같다.
var slice2 = array[1..]; // 끝값 생략 가능. 2,3,4,5,6,7
var slice2 = array[..]; // 배열의 모든 요소 복사. 1,2,3,4,5,6,7
var slice1 = array[1..^2]; // 2,3,4,5

 

System.Range 를 사용한 예제는 아래와 같다.

var array = new int[] { 1, 2, 3, 4, 5, 6, 7 };

Range range = new Range(1, 5);

foreach (var v in array[range])
{
    Console.WriteLine(v); // 2,3,4,5
}

 

System.Index, ^ 을 사용하여 범위를 지정할 수도 있다.

Range range = new Range(new Index(1), ^2);

// 정적 함수를 통한 범위 지정.
Range range1 = Range.StartAt(1); // 1 ~ 끝까지. 2,3,4,5,6,7
Range range2 = Range.EndAt(5); // 5 - 1 까지. 1,2,3,4,5
Range range3 = Range.All; // 모든 범위.