소켓 프로그래밍을 공부하다 알게 된 내용인데,
과연 다른 곳에 써먹을 일이 있을까 싶지만, 아무튼...
C#의 배열은 기본적으로 참조 타입이므로 아래와 같은 작업이 가능하다.
class Program
{
static void Main()
{
int[] arr1 = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] arr2 = arr1;
Console.WriteLine($"{arr1[0]} {arr2[0]}");
arr1[0] = 123;
Console.WriteLine($"{arr1[0]} {arr2[0]}");
}
}
위 코드처럼 arr2 에 arr1 을 대입하면 두 변수는 동일한 배열을 참조하게 되는 것을 알 수 있다.
(참고로 C++에서는 복사 생성자가 호출된다!)
그러나, 배열을 일부분만 참조하고 싶다면 얘기는 달라지는데...
class Program
{
static void Main()
{
int[] arr1 = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] arr2 = arr1[0..3];
Console.WriteLine($"{arr1[0]} {arr2[0]}");
arr1[0] = 123;
Console.WriteLine($"{arr1[0]} {arr2[0]}");
}
}
단순히 arr1 을 슬라이싱하여 arr2 에 대입하면, 이는 참조 범위를 조정하는 것이 아니라 실제 값을 복사하여 저장하는 것이 된다.
만약 참조를 원한다면, 슬라이싱이 아닌 ArraySegment<T> 구조체를 사용해야 한다.
class Program
{
static void Main()
{
int[] arr1 = new int[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
ArraySegment<int> arr2 = new(arr1, 0, 3);
Console.WriteLine($"{arr1[0]} {arr2[0]}");
arr1[0] = 123;
Console.WriteLine($"{arr1[0]} {arr2[0]}");
//Index out of range
Console.WriteLine(arr2[3]);
}
}
ArraySegment 생성자의 첫 인자는 참조하고자 하는 배열이고, 두번째 인자는 오프셋(시작 위치), 세번째 인자는 크기이다.
위 코드에서는 arr1 의 0번째 원소부터 3개, 즉 2번째 원소까지 arr2 가 참조하도록 하였다.
따라서, 0번째 원소는 정상적으로 참조가 가능했지만, 3번째 원소는 arr2 의 범위를 벗어나는 것을 확인할 수 있다.
'언어 > C#' 카테고리의 다른 글
Delegate와 Action, Func, Predicate (0) | 2023.07.20 |
---|---|
C#의 동작 원리 (0) | 2023.02.03 |
비교-정렬을 위한 두 인터페이스, IComparable과 IComparer (1) | 2022.10.02 |
댓글