스마트한 개발 공부/C#

[C#] Method의 Parameter 전달방식과 Shallow, Deep Copy

스마트한지노 2021. 8. 17. 19:23
728x90
반응형

Method를 만드는 방법에 대해서 설명했었는데 그렇다면 Method는 Parameter를 어떻게 전달할까?
2가지 방법이 있다.

1. Method의 Parameter 전달 방식

1.1 call by value

  • parameter에 값을 전달하기 때문에 호출한 쪽에서는 영향이 없다.
  • Reference Type은 값 자체가 인스턴스의 참조값이므로 call by Value를 하더라도 참조값이 전달되므로, 호출 전 전달 변수에 영향을 줌

1.2 call by reference

  • parameter에 참조값을 전달하기 때문에 호출한 쪽에도 영향이 있다.
    • 1. ref 키워드를 사용 : ref 키워드를 사용하고, 호출 전에 반드시 값을 할당한 상태에서 호출해야한다. 
    • 2. out 키워드를 사용 : 호출전에 선언만 하고, 값을 할당하지 않아도 변경된 값이 전달된다. 

2. Class를 사용한 전달 방식 비교하기

2.1 얇은 복사

class Point
{
    public int X { get; set; }
    public int Y { get; set; }

    public Point(int x, int y)
    {
        this.X = x;
        this.Y = y;
    }
    
    public override string ToString()  //객체 값 출력
    {
        return $"X:{X} Y:{Y}";
    }
}

간단하게 x, y 값을 받아서 객체를 만드는 class 코드이다. 다음은 2개의 숫자를 바꿔주는 swap 함수 사용해서 전달 방식을 확인하려 한다.

class ReferenceSwap
    {
        static void Main()
        {
        
        }    
        static void Swap(Point pt)
        {
            int temp = pt.Y;
            pt.Y = pt.X;
            pt.X = temp;

            Console.WriteLine(pt);
        }
        
        static void Swap(int x, int y)
        {
            int temp = x;
            x = y;
            y = temp;

            Console.WriteLine($"{x},{y}");
        }
    }

2개의 Swap 함수를 비교해서 호출 전 값과 호출 후의 값을 비교해보면

int x = 3;  
int y = 5;
Console.WriteLine($"X:{x} Y:{y}");  // X:3 Y:5
Swap(x, y);                         // X:5 Y:3
Console.WriteLine($"X:{x} Y:{y}");  // X:3 Y:5

Point p1 = new Point(3, 5);
Console.WriteLine(p1);              // X:3 Y:5
Swap(p1);                           // X:5 Y:3
Console.WriteLine(p1);              // X:5 Y:3

reference type인 class로 만든 객체의 호출 값은 Swap을 한 뒤에도 호출 전의 값이 영향을 받아 변경된 채로 유지되지만 int type은 변하지 않는다. 이를 얇은 복사라고 부르기도 한다. 그렇다면 그 값을 변경시키지 않고 이러한 함수를 어떻게 사용할까?

2.2 깊은 복사

깊은 복사에도 여러 가지 방법이 있다. 

2.2.1 새로운 인스턴스 생성

Point newPt = new Point(p1.X, p1.Y);
Swap(newPt);

호출하려는 객체의 value 값을 받아서 새로운 인스턴스를 생성하면 된다.

2.2.2 직접 함수를 만들기

위에 처럼하면 매번 인스턴스를 생성하는 코드를 작성해야 한다, 대신, 이를 만들어주는 함수를 만든다.

public Point DeepCopy()
{
    return new Point(this.X, this.Y);
}

//main 실행 코드
Swap(p1.DeepCopy());

2.2.3. net에서 제공하는 함수 사용하기

. net에서 ICloneable이라는 인터페이스에서 Clone()이라는 함수를 제공해준다. 하지만, 사용자 정의 함수는 Clone을 직접 만들어줘야 한다. array type은 직접 만들지 않아도 사용할 수 있다.

class Point :ICloneable
{
    public object Clone()
    {
        return new Point(this.X, this.Y);
    }
}

인터페이스를 상속받으면 Clone 함수가 없기 때문에 오류가 뜬다. ICloneable 인터페이스를 참조해서 만들면 된다.

Swap((int[])arr.Clone())

int로 이루어진 array 같은 경우는 위와 같이 하면 알아서 인스턴스를 만들어서 호출한다. 

728x90
반응형