Creative Commons License

Microsoft .NET

닷넷!시작하기
닷넷! Ver 2.0~
닷넷!스킬업
웹개발
윈폼개발
실용모듈개발
Tip & Tech
하루 한 문법

Microsoft .NET 개발자들을 위한 공간입니다. 기초강의에서 부터 고급 기술 정보 및 팁등을 다루도록 하겠습니다.

.

닷넷!스킬업

닷넷 기술을 조금 더 깊이 다루고자 합니다. 특정 주제를 정하지 않고 이슈 발생 시 마다 체계적으로 정리하여 공유하겠습니다. 이전 자료를 옮겨온 곳이기도 합니다.

참조형식을 참조로 전달???

작성자 : 박종명
최초 작성일 : 2010-03-18 (목요일)
최종 수정일 : 2010-03-18 (목요일)
조회 수 : 3763

한 때 이런 생각을 해 본적이 있습니다

 

객체는 참조형식인데 객체를 전달할 때 참조에 의한 전달을 할 필요가 있는가???

즉 객체변수 자체가 참조 값을 보유하고 있는데 또 참조 되도록 전달할 이유가 뭐가 있을까? 라구요

 

보통 참조에 의한 전달이 필요한 경우는 메서드 실행 시 변화된 변수 값을 유지하기 위해 사용합니다

참고: ref 와 out

 

값 형식의 변수를 전달하면 값 자체가 복사되어 원본과 복사된 값은 완전히 서로 다른 값이 됩니다

따라서 메서드 안에서의 변수 변화는 원본에 영향을 미치지 않습니다. 아래 코드는 이에 대한 예시입니다

 

int a = 10;

Method(a) //이 메서드 안에서는 a 값을 변경한다

//원본 a 는 변화 없다

 

만일 메서드 안에서의 변화 내용을 원본에서도 유지하고 싶을 경우 참조에 의한 전달을 이용합니다

 

Method(ref a) // 메서드 안에서 a 값을 변경하면 원본 a 도 변경된다

 

 

그러나 참조 형식인 객체는 조금 다릅니다

MyClass obj = new MyClass(10);

Method(obj) //이 메서드 안에서는 obj객체의 a 멤버 변수 값을 변경한다

//원본 obj a 변수 역시 변경된다

 

객체변수를 일반적으로 전달해도(값에 의한 전달) 객체변수 자체가 참조 값을 보유하고 있기 때문에

메서드 안에서의 변화 내용이 원본 객체에도 영향을 미칩니다

 

이 경우 굳이 ref 키워드를 사용해서 참조에 의한 전달을 이용하더라도, Method(ref obj) 결과는 동일합니다

 

그러므로 언뜻 객체를 ref 로 전달할 이유를 찾지 못했습니다

지금부터 객체도 참조에 의한 전달을 할 필요가 있는 경우와 그 원리에 대해 살펴보도록 하겠습니다

 

 

참조형식 메모리 구조

닷넷의 자료형은 값 형식(Value Type) 과 참조 형식(Reference Type)으로 구분된다.클래스에 기반한

객체(인스턴스)는 대표적인 참조형식 자료이다. 참조형식의 변수는 메모리에 데이터 자체가 들어가는

것이 아니라 데이터가 저장된 메모리의 참조 값이 저장되는 구조이다

 

MyClass obj = new MyClass(10);
위와 같이 객체를 생성하면 객체변수 obj는 실제 객체 Data가 저장된 메모리에 대한 참조를 가지게 된다

 

 

 

매개변수 전달 방식(값에 의한 전달, 참조에 의한 전달)

메서드로 매개변수를 전달할 때 값 자체를 복사해서 전달하는 방식(Call By Value)과 값이 저장된 메모리의

참조를 전달하는 방식(Call By Reference)이 있다. 닷넷은 기본적으로 값에 의한 전달 방식으로 매개변수를

전달한다. 만일 참조에 의한 전달을 하고자 한다면 ref 키워드를 이용하면 된다

 

우선 테스트를 위해 다음과 같은 클래스와 코드가 정의되어 있다고 가정한다

 

class MyClass{

   public int a;

   public MyClass(int i){

       this.a = i;

   }

}

 

static void Method(MyClass obj){         

      ob.a = 20;         

}

 

 

 

객체 전달) 값에 의한 전달

객체변수를 값에 의한 전달을 하게 되면 객체변수가 가진 참조 값 자체가 복사된다

아래와 같이 코드를 작성하면,

 

MyClass obj = new MyClass(10);

Method(obj);

 

원본 obj의 참조 값이 매개변수 obj로 복사되어 두 변수는 동일한 객체를 가르키는 구조가 된다

따라서 메서드 안에서 객체 값을 변경하면 원본(obj)도 그 변경 사항이 유지되는 것이다

 

 

객체 전달) 참조에 의한 전달

반면 객체변수를 참조에 의한 전달을 하게 참조 값이 복사되는 것이 아니라 원본 객체 변수를

또 다시 참조하게 되는 구조가 된다

 

MyClass obj = new MyClass(10);

Method(ref obj); //Method 메서드에 ref 매개변수로 정의되었다고 가정한다

 

즉 다음 그림과 같이 원본 obj 메모리를 간접 참조하게 되는 것이다

 

앞의 값에 의한 전달 방식과는 구조가 다르지만 실제 객체 값의 변경이 유지되는 것은 동일하다

 

즉 값에 의한 전달이나 참조에 의한 전달이나 모두 메서드 안에서 객체 값을 변경하면 원본(obj)

그 변경 사항이 유지되는 것이다

 

 

그렇다면 어떤 경우에 객체를 참조에 의한 전달을 해야 할까?

 

그것은 바로 객체변수 자체를 변경하고 싶을 경우이다

 

즉 실제 객체 Data가 아니라 원본 객체변수(obj) 자체를 변경하고자 할 경우에 참조에 의한 전달을 해야 한다.

아래 코드를 보자. 값에 의한 전달 이후 메서드 안에서 새로운 객체를 생성하고 있다

 

 

static void Main(string[] args){         

    MyClass obj = new MyClass(10);

    Console.WriteLine("1.원본 obj의 값:" + obj.a);

    Method(obj);

    Console.WriteLine("3.호출 이후 obj의 값:" + obj.a);       

}

 

static void Method(MyClass obj) {

    obj = new MyClass(20); //새 객체를 할당해 버린다

    Console.WriteLine("2.새 객체 값:" + obj.a);

}

 

결과>> 아래 결과를 보면 메서드 내에서의 변화가 원본에는 영향을 미치지 않고 있다는 것을 알 수 있다

즉 메서드 안에서는 새로운 객체를 생성해서 값도 변경했는데 메서드 호출 이후에는 여전이 이전 객체 정보가

남아 있다는 것이다

 

 

 

이 코드를 참조에 의한 전달을 변경하면 결과는 다음과 같다

(ref 키워드를 사용하여 참조의 의한 전달로 코드를 수정했다고 가정한다)

 

결과는 메서드 안의 변화 내용이 원본에서 미쳤음을 알 수 있다

 

Method 메서드 안에서의 다음의 코드는 객체 데이터가 아니라 객체 변수 obj 자체를 변경하고 있는 것이다

obj = new MyClass(20);  

 

값에 의한 복사에서는 obj 참조 값이 복사된 곳에서 새로운 객체를 참조하기 때문에 원본(obj)에는

영향을 미치지 않게 되는 것이며, 참조에 의한 복사에서는 원본(obj) 자체가 새로운 객체를 가르키도록

변경되는 것이다. 아래 이 과정을 도식화 한 그림이다

 

 

이와 같이 참조형식인 객체도 참조에 의한 전달을 해야만 하는 경우가 있을 수 있다

MSDN에서는 참조형식인 두 문자열(string)을 교환하는 샘플을 예시로 들고 있다

 

마지막으로 IL 코드에서도 두 방식의 차이점을 확인할 수 있다

1) 값에 의한 전달

 

 

 

2) 참조에 의한 전달

매개변수 MyClass & 붙었다. 참조에 의한 전달은 C++의 레퍼런스와 같이 키워드(&) 가 붙여 있다

그리고 원본 객체 변수를 간접 참조하는 코드가 추가되어 있는 것을 볼 수 있다

 

 

 

 

이름
비밀번호
홈페이지
EL <- 왼쪽의 문자를 오른쪽 박스에 똑같이 입력해 주세요