http://genamics.com/developer/csharp_comparative_part6.htm
8. 구조체
“단지 여러분이 필요하기 때문에 정말로 효율적인 코드를 작성하기 위한 한가지 방법”으로만이 아닌 C#의 타입체계가 좀 더 우아하게 돌아가게 만들어주는 구성요소의 하나로서 C#의 구조체를 살펴보는 것도 유익한 일이다.
C++에서는 구조체와 클래스(객체) 둘다 스택/인라인 혹은 힙에 할당될 수 있다. C#에서는 구조체는 항상 스택/인라인 영역에 생성되며 클래스(객체)는 항상 힙에 생성된다. 구조체는 실제로 좀 더 효율적인 코드를 작성할 수 있도록 해준다:
public struct Vector {
public float direction;
public int magnitude;
}
Vector[] vectors = new Vector [1000];
위 코드는 1000개의 벡터(Vector)를 모두 한 곳에 집어넣을 공간을 할당할 것이며, 우리가 벡터를 하나의 클래스로 선언하고 for 반복문을 이용하여 1000개의 각 벡터를 인스턴스화하였으므로 훨씬 더 효율적이다. 우리가 효율적으로 해낸 부분은 우리가 C#s이나 Java에서 정수형 배열(int array)을 선언하는 것과 비슷하게 선언된 배열이다:
int[] ints = new ints [1000];
C#은 여러분이 언어에 내장되어 있는 원형 타입(primitive)들을 간단하게 확장할 수 있도록 해준다. 사실 C#은 모든 원형타입을 구조체로서 구현한다. int 타입은 단순히 System.Int32 구조체의 별칭일 뿐이며 long 타입은 System.Int64 구조체 등의 별칭일 뿐이다. 이러한 원형타입들은 당연히 컴파일러에서 특별하게 처리될 수도 있지만 언어 자체는 그러한 구분을 짓지는 않는다. 다음 섹션은 C#이 이러한 것들을 어떻게 이용하는지 보여줄 것이다.
9. 타입 단일화(Type Unification)
대부분의 언어는 원형타입(int, long 등)과 궁극적으로는 원형 타입들로 이루어진 고수준의 타입들을 가지고 있다. 그것은 종종 원형타입과 고수준 타입들을 동일한 방식으로 다룰 수 있기 때문에 유용하다. 예를 들어 정수 뿐만 아니라 문자열 모두를 가질 수 있는 컬렉션을 갖는 것이 유용할 때가 있다. 스몰토크(smalltalk)는 어느정도의 효율성을 희생하고 int와 long을 String이나 Form으로 다루게 함으로써 이것을 가능하게 하고 있다. Java는 이러한 효율성을 희생하는 것을 피하여 C나 C++에서와 같이 원형타입을 다루지만 각각의 원형 타입에 대응되는-int는 Integer에, double은 Double에- 래퍼(Wrapper) 클래스를 제공하고 있다. C++의 템플릿(template)은 타입에 대한 연산을 그 타입에서 제공하는 한 어떠한 타입도 받아들이도록 작성된 코드를 짤 수 있도록 해준다.
C#은 이러한 문제에 대하여 색다른 해결책을 제공한다. 이전 섹션에서 필자는 어떻게 int와 같은 원형 타입이 단순히 구조체에 대한 별칭일 뿐이었는지를 설명하면서 C#의 구조체를 소개하였다. 이는 구조체가 object 클래스가 가진 모든 메소드를 갖기 때문에 다음과 같은 코드를 짤 수 있도록 해준다:
int i = 5;
System.Console.WriteLine (i.ToString());
만약 구조체를 객체로 사용하고 싶을 경우, C#은 구조체를 객체로 박싱할 것이며 다시 그것을 구조체로 사용하고 싶을 때에는 언박싱해줄 것이다.
Stack stack = new Stack ();
stack.Push (i); // box the int
int j = (int) stack.Pop(); // unbox the int
구조체를 언박싱할 때 필요한 형변환과는 상관없이 이는 여러분이 구조체와 클래스간의 관계를 일관성 있게 처리하는 방법이다. 여러분은 비록 CLR이 박싱된 객체에 대한 별도의 최적화를 제공해 줄지는 몰라도 박싱이 래퍼 객체를 양산하는 것을 수반한다는 것을 털어놓아야 할 것이다.
C#의 설계자들은 설계 과정동안 템플릿을 고려해야만 했다. 필자는 템플릿을 사용하지 않은 이유에 대해 두가지 주요 원인이 있었으리라 짐작하는데, 그 첫번째는 설계가 난잡해 질 수 있다는 점이다. 템플릿은 어려워서 객체지향적인 특성들을 뒤죽박죽 섞어놓을 수 있고, 템플릿은 프로그래머에게 너무 많은(혼란스러울 정도로) 설계 가능성을 열어주며, 리플렉션(reflection)과 결합하기가 어렵다. 두 번째 이유는 컬렉션과 같은 닷넷 라이브러리가 템플릿을 사용하지 않을 경우 템플릿은 그렇게까지 유용하지는 않을 것이라는 점이다. 그러나 만약 닷넷 클래스에서 템플릿을 사용했다면 닷넷 클래스들을 사용하는 20개 이상의 언어들도 템플릿도 결합해야만 했을 것이며, 이를 기술적으로 이뤄내기가 상당히 어려웠을지도 모른다.
템플릿(제네릭)이 Java Community Process에 의해 Java 언어에 포함할 것을 고려중이라는 것도 흥미로운 일이다. 그렇게 되면 각 기업은 Sun에서 “닷넷은 최소 공분모 신드롬(lowest common denominator syndrome)을 겪고 있다”라고 말하고 Microsoft는 “Java는 교차 언어(cross-language support)를 지원하지 않는다”라고 말할 때부터 서로의 곡조에 맞춰 노래를 부르기 시작한지도 모르겠다.
(8월 10일 수정) Anders Hejlsberg의 인터뷰를 읽은 후로 위에서 제시했던 어려움 때문에 첫 번째 릴리즈는 아니지만 템플릿이 나타날 것이 임박해졌다. 바이트 코드(byte-code)는 아니지만 중간언어(IL) 스펙이 IL 코드가 템플릿을 표현(리플렉션과 잘 어울릴 수 있도록 비파괴적인(non-destructive) 방법으로)할 수 있도록 작성되어 졌음을 살펴보는 것도 매우 재미있었다. Java에 제네릭을 도입하려고 고려중인 Java Community Process에 관한 링크도 첨부한다: