메서드 매개변수에 값 전달.

“자신을 연민하지 않는다.”

모르는게 먼지도 모르지만, 이건 확실히 모르겠다고 얘기할 수 있습니다. 으하하;;

class Movie {
  public string? Title {get;set;}
}

class Program {
  static void Main() {
    var movie = new Movie { Title = "Movie 1" }

    ChangeMovieTitle(movie);
    Console.WriteLine(movie.Title);
    // Title 변경됨.

    AllocateNewMovie(movie);
    Console.WriteLine(movie.Title);
    // Title 변경안됨.
  }

  static void ChangeMovieTitle ( Movie movie ) {
    movie.Title = "Changed Movie";
  }

  static void AllocateNewMovie ( Movie movie ) {
    movie = new Movie { Title = "New Movie" }
  }
}

AllocateNewMovie 에서 할당한 Title 반영이 안되는건가요???

5개의 좋아요

제가 댓글 달 때 쯤 다른 분이 먼저 달 거 같은데
두 번째 메서드에선 새 객체를 할당해주기 때문에 안바뀌는겁니다.
new 를 쓰는 순간 Main에 있던 Movie 객체가 아니란거죠

자세한건 다른 분이 단 댓글을 보시거나… 구글에 ‘값 타입 참조 타입’ 검색하시면 됩니다.

5개의 좋아요

자신을 부끄러워하거나 연민할 필요 없습니다. 질문 잘 하셨어요!

이유는 @태현짱와우 님이 잘 설명했습니다.
매개변수로 전달된 movie가 메소드 밖의 movie인 것 처럼 동작하는 이유는 movie가 참조 변수이기 때문입니다. 실제로는 다른 스택 주소를 가지는 다른 변수입니다. 다른 변수가 동일한 참조 개체를 바라보고 있을 뿐이죠.

그런데 메소드 안의 movie가 새로운 Movie 개체를 받게 될 때 이때부터 동일한 참조 개체를 바라보는 것이 아니라 다른 개체를 바라보게 됩니다.

5개의 좋아요

C#에서는 메서드에 인자를 전달할 때, 값을 전달하는 방식과 참조를 전달하는 방식 두 가지가 있습니다. 값을 전달하는 방식은 변수의 값을 복사하여 전달하며, 참조를 전달하는 방식은 변수의 참조를 전달하여 해당 객체를 공유합니다.

AllocateNewMovie 메서드의 매개변수 movie는 참조를 전달하는 방식으로 전달되기 때문에, 메서드 내에서 변수 movie의 값을 변경하면 원래의 변수에도 영향을 미칩니다.

그러나 AllocateNewMovie 메서드 내에서 새로운 Movie 객체를 할당하는 것은 메서드 내의 지역 변수에 대한 작업이므로, 원래의 movie 변수에는 영향을 주지 않습니다.

즉, movie 변수는 여전히 원래의 Movie 객체를 참조하게 됩니다.

5개의 좋아요

!!! 닷넷데브 실시간 모니터링 중이신 겁니까???

!!!. 값 전달시 복사본 전달.

  1. Main 메서드 내의 movie 는 Movie객체의 주소값.
  2. ChangeMovieTitle 메서드에서 Main메서드의 Movie객체 주소값 변경없어, Title 수정됨
  3. AllocateNewMovie 메서드에서는 new 연산의 결과로 새로운 주소값이 복사된 move 변수에 저장되어, Main 메서드내의 movie 주소값과 달라져 Title 변경안됨.

세분 모두 진심으로 고맙습니다!!!

4개의 좋아요

저 때는 신기하게 저 개념이 익숙해지신 다음에
우릴 고통 받게 하던
포인터를 다시 보시면 또 뭔가가 다르게 보이더라고요 ㅎㅎ

1개의 좋아요

와 저는 개념을 다시 잡아야겠네요;;; 당연히 기존 변수 movie를 참조로 전달해서 재성생했기 때문에 main의 movie 주소값은 변경이 없어 재생성되는지 알았는데 ;; 만약 AllocateNewMovie에 movie에 this를 추가하여 new 키워드로 재생성하면 값은 변경이 되는건가…

2개의 좋아요

ref 로 참조 형태로 전달 하시면 됩니다.

3개의 좋아요

일반적으로 새로 값을 할당하는 경우가 아닌 이상 이런 문제를 겪을 일이 없다보니 간과하기 쉬운데, Pass by reference라고 생각하지만 Pass a reference type by value입니다. 값 타입 변수든 참조 타입 변수든 기본적으로는 값 복사로 전달됩니다. 다만 값 타입 변수는 변수에 저장된 값이 복사되고, 참조 타입 변수는 해당 변수가 참조하는 주소가 복사되는 점이 다릅니다.

  • 값 타입 변수 - 변수에 저장된 값의 복사본을 전달
  • 참조 타입 변수 - 변수가 참조하는 메모리 주소의 복사본을 전달
void Foo()
{
    Person person1 = new();
    Bar(person1);
}
void Bar(Person person2)
{
    person2 = new();
}

Foo()의 person1과 Bar(Person person)의 person2는 같은 메모리 주소를 참조하는 다른 변수입니다. c 계열의 포인터처럼 person2가 person1을 가리키는 게 아닙니다. 즉 Bar에서 person2에 새 객체를 할당하여 변수가 가리키는 주소값을 수정하면 person1과 person2가 서로 다른 주소를 참조하게 됩니다.

다른 분들 말씀처럼 ref 키워드를 붙여 Pass by reference로 동작하게 해주면 person2이 person1을 참조하기 때문에 person2에 새 객체를 할당하면 person1에 수정사항이 반영됩니다.

6개의 좋아요

닷넷 문서의 매개 변수 편에서는 아래와 같이 표현하더군요.

Passing a copy
지역변수/필드/매개변수의 복사본을 전달.
값타입 => 값이 복사, 참조타입 => 참조값

Passing access
in/out/ref 키워드를 사용하여 변수에 대한 접근권 전달.

위 문서와 다른 부분에서는, 때로는 "변수 자체를 전달"한다는 개념으로 설명하기도 하고, 때로는 "지역 내에서만 유효한 변수에 대한 별칭"이라고 설명하기 하더군요.

변수 편에 있는 Pass by reference , Pass by value 구분보다는 위의 구분이 훨씬 더 명확한 것 같습니다.

5개의 좋아요

확실히 copy와 access 개념으로 가져가니 좀 더 명확해지는 느낌입니다.
역시 msdn

3개의 좋아요