C#에서는 배열이 참조 타입이기 때문에,
배열을 메서드에 전달할 때 배열을 실제 데이터를 전달하는 것이 아니라 배열에 대한 참조가 전달됩니다.
이는 메서드 내부에서 배열을 수정할 경우, 원본 배열도 영향을 받는다는 것을 의미하며
이번 포스팅은 회사 프로젝트를 진행하며 잊고 있었던 내용을 정리하려고 작성했습니다.
| 문제 상황 (예시)
int[] numbers = { 1, 2, 3, 4 };
ModifyArray(numbers);
Console.WriteLine(string.Join(", ", numbers)); // 예상: 1, 2, 3, 4 / 실제: 10, 2, 3, 4
void ModifyArray(int[] arr)
{
arr[0] = 10;
}
위 코드에서 ModifyArray 메서드가 매개변수로 받은 numbers 배열의 첫 번째 값을 변경했습니다.
때문에, 호출 후에도 numbers 배열이 수정됩니다.
원본 배열을 그대로 유지하고 싶다면 배열을 복사한 후 전달하면 해결할 수 있습니다.
| 배열 복사 방법
배열의 참조 대신 복사본을 전달하는 방법은 배열이 수정되는 것을 방지할 수 있습니다.
c#에서 배열의 참조 대신 복사본을 전달하는 방법은 주로 2가지를 사용합니다.
| Array.Copy
int[] numbers = { 1, 2, 3, 4 };
int[] copyNumbers = new int[numbers.Length];
Array.Copy(numbers, copyNumbers, original.Length);
ModifyArray(copyNumbers);
Console.WriteLine(string.Join(", ", numbers)); // 예상: 1, 2, 3, 4 / 실제: 1, 2, 3, 4
void ModifyArray(int[] arr)
{
arr[0] = 10;
}
이번에는 문제 상황의 코드에서 numbers를 Array.Copy를 이용해서 copyNumbers로 바꾸었고
copyNumbers 배열을 ModifyArray에 전달했으며
처리 후 numbers 배열을 확인해 보시면 numbers 배열의 항목이 유지되는 것을 확인할 수 있습니다.
| Array.Clone
int[] numbers = { 1, 2, 3, 4 };
int[] cloneNumbers = (int[])numbers.Clone();
ModifyArray(cloneNumbers);
Console.WriteLine(string.Join(", ", numbers)); // 예상: 1, 2, 3, 4 / 실제: 1, 2, 3, 4
void ModifyArray(int[] arr)
{
arr[0] = 10;
}
Clone을 사용하면 Array.Copy를 이용하는 것보다 간단하게 복사할 수 있으며
동일한 결과를 확인할 수 있습니다.
| 주의할 점
- Array.Copy와 Array.Clone를 사용하는 것은 얕은 복사를 수행합니다.
따라서 1차원 배열의 경우 복사본이 잘 작동하지만 다차원 배열이나 객체를 참조하는 배열에서는 주의가 필요합니다.
이런 경우에는 개별적으로 배열 요소를 복사하거나 직접 깊은 복사를 구현해야 합니다.
(얕은 복사와 깊은 복사에 대한 내용은 따로 포스팅하겠습니다.)
예제) 깊은 복사 구현
int[] numbers = { 1, 2, 3, 4 };
int[] deepCopyNumbers new int[numbers.Length];
for(int i = 0; i < numbers.Length; i++)
{
deepCopyNumbers[i] = numbers[i]
}
ModifyArray(deepCopyNumbers);
Console.WriteLine(string.Join(", ", numbers)); // 예상: 1, 2, 3, 4 / 실제: 1, 2, 3, 4
void ModifyArray(int[] arr)
{
arr[0] = 10;
}
- 또한 배열의 크기가 클 경우 복사본을 만드는 것은 메모리를 많이 소모할 수 있으므로
성능이 중요한 환경에서는 배열 복사에 대한 최적화 방안을 고려해야 합니다.
| 마무리
프로젝트를 진행하다 보면 배열을 복사해서 처리해야 하는 일이 가끔 있는데
저는 Clone을 사용해서 냅다 하는 것 같네요ㅎㅎ
틀린 점이나 질문이 있으시면 댓글로 남겨주세요
감사합니다 :)
'C#' 카테고리의 다른 글
C# 정규 표현식(Regular Expression) 이해 (0) | 2024.10.26 |
---|---|
C# Enum 열거형에서 Name, Value 처리하는 방법 (0) | 2024.10.06 |
C# Modbus TCP 통신 뚫기 : NModbus 라이브러리 사용 (4) | 2024.10.03 |
C# 네트워크 통신을 위한 BitConverter 클래스 이해 (0) | 2024.03.18 |
C# Byte 통신을 위한 Array 클래스 이해 (0) | 2024.03.15 |