페이지

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로 구현되어 있는 것을 볼 수 있었다..




2013년 5월 20일 월요일

Visual Studio 와 Mono Develop 의 소스코드 인코딩 방식

개인적으로 MS Visual Studio가 편하기 때문에 주로 VS로 소스코드를 작성하고 있다. 하지만 Unity에서 디버깅을 하기 위해선 Mono 역시 버릴 수 없는 상황인지라.. 두 에디터를 동시에 사용하고 있는데.. 두 에디터의 소스코드 저장방식이 달라 몇가지 불편한 점이 있다.

<Line Einding 방식>
Visual Studio : Windows (CR LF)
Mono : Unix (LF)

<소스코드 인코딩 방식>
Visual Studio : Korean - Codepage 949
Mono : UTF-8

위와 같이 되어있기때문에 VS에서 한글 주석을 달으면 Mono에서 한글이 깨져나오게 된다.
그래서 한가지 방식으로 통일하였는데.. 대부분 Unity 에디터에서 파일을 생성하기 때문에 Mono방식으로 통일하기로 했다.
또한 Codepage 949 방식은 MS가 개발한 한글 인코딩 방식으로 EUC-KR과 비슷한 방식이다. 하지만 Mono에서는 Codepage 949 형식을 지원하지 않기때문에 충돌이 날 수 있다.

결론은 UTF-8방식으로 인코딩을 설정하면 된다.

VS에서 설정을 바꾸려면 프로젝트가 열린 상태에서

FILE > Advanced Save Options 에서 Encoding: Unicode (UTF-8 with signature) - Codepage 65001
Line endings: Unix(LF)

p.s: 인터넷 서핑하다 발견한 한가지 사실: Unix(LF)로 저장할시 Visual Studio에서 break point가 잘 안 잡힐 수 있다고 한다. 내경우엔 현재 VS로 디버깅 할 일이 없어.. 그냥 쓰기로 함.

위와 같이 설정하더라도 매번 소스파일을 생성할때 기본값으로 생성되므로 매크로를 이용해 UTF-8파일을 생성하고 싶다면 아래 링크를 참고하면 될 것 같다.

http://nving.tistory.com/66