페이지

2013년 5월 21일 화요일

struct 와 class In C#

C++의 경우 struct와 class의 차이는 선언된 변수나 함수가 기본적으로 public 이나 private이냐의 차이이다. class의 경우 private이 기본으로 선언된다. 이는 C++ 언어의 encapsulation 의 메카니즘에 의한 차이로 보인다.

그럼 C#에서 struct와 class 의 차이는 뭘까..

C++에서와 달리 두가지 모두다 private 으로 기본 선언된다.
또한 Structs는 파라미터가 없는 Constructor를 가질 수 없다.

// 구글을 검색하면 아래와 같은 글이 많이 보인다.. 하지만 몇가지 아티클과 책을 읽은 후 이부분에 의심이 생기기 시작함... 흠..

  • struct의 경우 stack 에 저장되고 class의 경우 heap에 저장된다.


저 말은 struct가 value type이기 때문에 stack 에 저장된다고 하는거 같지만.
아래 글을 보면 의심이 들기도 한다. 단지 value type이라고 해서 stack에 저장되지 않는다는 말이다. 메모리의 어떤위치에 저장 될 것인가는. 변수의 life time에 따라 컴파일에서 정해진다고 한다. 그래서 일반적으로 (MS VS의 경우) 임시변수나 로컬변수가 stack 에 저장된다는 것이다.
http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

struct로 생성 할 경우 memory fragmentation 의 경우도 발생되지 않을 것 같고.. Garbage Collection의 호출도 줄 일 수 있을거 같다...고 생각했지만 지금은 이부분도 좀더 생각해봐야겠다..;;

여기서 분명히 다른 점은 struct의 경우 함수 parameter로 넘길때 pass by value로 인식하기 때문에 reference 로 값을 넘겨야한다. 반대로 class의 경우 pass by reference 로 넘어간다.

아래 struct가 pass by value로 처리되는 예제이다.



public struct TestStruct
{
    public int value;
}

public class TestClass
{
    void function(TestStruct ts)
    {
        ts.value = 5;
    }

    void main()
    {
        TestStruct ts = new TestStruct();
        ts.value = 10;

        function(ts);

        Console.WriteLine("{0}", ts.value);
    }
}


Output: 10

이로인해 생기는 문제가 있는데..


public struct TestStruct
{
    public int value;
}

public class TestClass
{
    void function(TestStruct ts)
    {
        ts.value = 5;
    }

    void main()
    {
        TestStruct ts = new TestStruct();
        ts.val = 10;

        List<TestStruct> list = new List<TestStruct>();
        list.Add(ts);

list[0].val  = 5;

        Console.WriteLine("{0}", list[0].val);
    }
}

위에서 처럼 List에 Add했을 경우 임시변수에 값을 할당하게 되어 에러가 발생한다.

간단히 해결하는 방법은



void main()
{
    TestStruct ts = new TestStruct();
    ts.val = 10;

    List<TestStruct> list = new List<TestStruct>();
    list.Add(ts);    

TestStruct temp = new TestStruct();
temp.val = 6;
list[0]  = temp;

    print(list[0].val);
}

메모리를 새로 할당해서 값을 셋팅한후 넘겨주거나
Custom Container를 만들어서 operator = 오버라이딩을 할까 했으나...-_-

msdn에 문서에서 = 은 오버라이딩을 할 수가 없다...oTL

http://msdn.microsoft.com/ko-kr/library/8edha89s(v=vs.71).aspx

뭐 그래서 위에처럼 처리하면 될 것 같다...털썩..

아 그리고 오버라이딩이 안된다면 Deep Copy를 이용해 하는 방법도 있을듯... 이건 직접 해보지 않아 아직 확실하진 않다..-_-ㅋ


어제 저걸 고민하다가 Unity3D에서는 struct를 어떻게 사용했나 궁금해서 봤더니..
Vector가 struct로 구현되어 있었다.. 반면 GameObject의 겨우 extern 의 외부 객체들을 들고 있어 class로 구현되어 있는 것을 볼 수 있었다..




댓글 없음:

댓글 쓰기