C# List 참조 질문입니다...

안녕하세요…

참조관련 질문드립니다…

다른클래스에 List 필드를 A ,

또다른 클래스에 A와 구조가 같은 지역변수로 선언한 List 를 B라고 할때

A = B 이후에

B = null 로하면

A = null 이 될줄 알았는데
A는 List 값이 있더라고요,

혹시 왜 null 로 안바뀌는지 알 수 있을까요 ㅠㅠ;;


[DataContract]
public class ClassInfo
{
    [IgnoreDataMember]
    public List<ClassA> ClassA = new List<ClassA>();
}

main.cs
.
.
.
public void function()
{
    
    List<ClassA> listClassA = new List<ClassA>();

    // DB 값을 조회해서 ds에 담았음

    foreach (DataRow dr in ds.Tables[0].Rows)
    {
        
        ClassA classA = new ClassA();
        
        // 반복해서 값을 대입
        classA.field1 = dr["field1"].ToString();
        ...
        // 리스트에 Add
        listClassA.Add(classA);
    }
    
    listClassA 

    // A = B 처리
    // StaticInfo 는 static 입니다 [public static StaticInfo staticInfo = new staticInfo();]
    staticInfo.ClassInfo.ClassA = listClassA;

    // B = null 처리
    listClassA = null

    // 궁금한 부분은 제가 얕은 복사 개념으로 접근해서 그렇긴한데
    // listClassA = null 처리하면 ClassA 도 null 이 될줄 알았는데
    // ClassA는 값이 살아있는점에 대한 개념이 부족한 것 같습니다....저는 null 로 변경될줄 알았어요 ㅠㅠ
}


5개의 좋아요

일단은 예시를 주실 때 예제 코드를 첨부하시면 이해가 빠를 것 같습니다.

설명해주신 내용을 코드로 만드는 것은 크게 어렵지 않을 듯하고, markdown언어로 코드 첨부하는 방법을 검색해보시면 많이 나옵니다.


말씀하신 부분은 class는 참조타입이고 예시로 드신 List도 class 이기 때문입니다.

실제로 인스턴스가 힙 영역에 있고 A와 B는 그냥 주소만 들고 있는 것입니다.

때문에 B = null; 을 하신 것은 B라는 공간 안에 들어있는 주소를 null로 만드신 것입니다.

이미 이전에 List 인스턴스가 A와 B에 모두 참조가 걸려있었으니 B 공간에 null이 들어갔다고 해서, A의 주소값이 사라지지는 않는 것입니다.

null을 대입하시는 게 인스턴스를 제거한다는 개념이 아닌 것을 이해하시면 됩니다.

그리고 null을 대입하시는 행위가 메모리를 제거하고 싶으신 의도시라면, A와 B에 둘 다 null을 넣으시고, 시간이 흐르면 GC가 우리가 알지 못하는 순간에 메모리를 회수하고 압축합니다.

4개의 좋아요

짧은 지식으로…얕은 복사 개념으로 봐서 b를 null 로하면 a도 null 이 될줄알았습니다…

5개의 좋아요
A = B;

이 행위는 얕은 복사의 개념이 맞습니다.
얕은 복사는 참조만 복사되는 것이고 실제 인스턴스가 복사되는 개념이 아닙니다.
실제 인스턴스가 복사되어야 깊은 복사라고 합니다.

따라서 A와 B가 같은 주소를 가지고 있기 때문에 얕은 복사가 맞습니다.
그리고 B의 공간을 null로 만드셨기 때문에, A의 공간은 그대로 주소 값이 들어 있습니다.


통상적으로 얕은 복사에 대해선 참조를 캐싱하는 개념과 유사하기 때문에 .NET에서 지원하지만, 깊은 복사에 대해서는 실제 인스턴스에 대해서 얼마만큼 복사할지를 가늠하기 어렵기 때문에 깊은 복사는 수동으로 직접 구현해야 하는 경우가 많습니다.
복잡한 클래스의 경우엔 참조들이 재귀적으로 참조 걸려있는 경우도 더러 있기 때문에 깊은 복사를 BCL 라이브러리 같은데서 함부로 지원할 경우 엄청난 메모리 낭비가 있을 수도 있습니다.
그런 헛점을 만들바에는 지원을 안하고 사용자 입맛에 맞게 본인이 직접 구현하는 게 맞을 것 같습니다.

대표적으로 사용되는 깊은 복사의 방법은 Json직렬화/역직렬화를 이용하는 것입니다.
객체에 대해 직렬화를 하면 엄청나게 긴 string이 나올 것이고, 그것을 역직렬화하여 새로운 객체를 만들어내면, 기존의 객체와 값이 같지만 인스턴스가 다르기 때문에 이런 경우 깊은 복사의 개념을 가지고 있다고 할 수 있습니다.

7개의 좋아요

선생님…markdown언어로 코드 첨부하는 방법 참고해서 뒤늦게 올려드립니다…답변 너무 감사드립니다. 허접한 질문에도 불구하고 초보자 눈높이로 설명해주셔서 정말 감사합니다

6개의 좋아요