본문 바로가기

IT 살이/04. 기술 - 프로그래밍

LINQ 시리즈 06 - Object initializer, 익명 타입(anonymous types) II

앞의 포스트에서 Object initializer에 대해서 알아봤다. 먼저 읽어보는 것이 좋을 듯 싶다. 이제 익명 타입(anonymous types)을 알아보자. C#3.0부터는 다음과 같은 표현이 가능해진다.

Customer c1 = new Customer{ Name="달봉이"};

var c2 = new Customer{Name="봉달이"};

var c3 = new {Name="봉봉이", Age=30 };

var c4 = new {c2.Name, c2.Age };

var c5 = new { c1.Name, c1.City};

var c6 = new {c1.City, c1.Name};

c1 생성은 앞에서 배운 객체 초기화 코드이다. c2는 Customer 객체를 초기화해서 var 타입에 할당하고 있다. var 키워드가 사용되면 할당된 표현식으로부터 변수의 타입을 유추해낸다. 해서 c2는 Customer 타입이라는 것을 알아낸다.

근데, c3,c4,c5,c6이 이상하다. 타입이름이 없다. 그렇다. 타입 이름이 없다. 굳이 타입 이름을 밝히지 않아도 되는 경우가 있다는 것이다. 그런 경우 굳이 이름을 지을 필요는 없다. 이런 경우는 컴파일러가 내부적으로 타입 이름을 지어주고 var의 타입 결정단계에서는 내부에서 생성한 타입으로 결정된다. 내부에서 자동 생성된 타입에는 initializer에서 사용된 공개 속성 또는 멤버에 해당하는 공개 속성과 해당 전용 멤버가 정의된다.  그 공개 속성과 내부 전용 멤버의 이름과 타입은  initializer에서 사용된 예를 들어 {Name="봉봉이", Age=30}를 통해서 유추된다.

c1~c6의 타입을 출력해보면 다음과 같다.

Console.WriteLine("c1 is {0}", c1.GetType());

Console.WriteLine("c2 is {0}", c2.GetType());

Console.WriteLine("c3 is {0}", c3.GetType());

Console.WriteLine("c4 is {0}", c4.GetType());

Console.WriteLine("c5 is {0}", c5.GetType());

Console.WriteLine("c6 is {0}", c6.GetType());

1155834665

LINQ 쿼리에서는 코드상에서 타입 이름은 필요없고, 단지 공개된 속성을 통해서 객체에 대한 쿼리만이 필요하다. 예를 들어 Name이 "달봉이"인 객체를 조회하는 쿼리문에서 타입이 뭔지는 필요없다. Name이라는 속성이 공개되어있고 그 타입이 string이면 된다.

앞의 포스트에서 C#1.x에서도 다음과 같은 표현이 가능했다고 했다.

string[] names = {"달봉이", "봉달이", "봉봉이"};

C#3.0에서는 배열을 초기화하는 표현이 var, 익명 타입과 object initializer를 이용해서 훨씬 강력해졌다.

var c = new [] {

    new { Name="달봉이", Sports=new[] { "테니스", "축구"} },

    new { Name="봉달이", Sports=new[] { "럭비", "골프"} },

    new { Name="봉봉이", Sports=new[] { "숨쉬기", "뒹굴기"} }

};

변수 c는 배열인데, 그 요소의 타입은 모두 이름이 없고 다만 속성으로 string 타입의 Name과 string배열의 Sports를 갖고 있는 요소들이다. 이 표현을 통해서 내부적으로는 타입의 이름보다는 그 타입의 구조만 알 수 있으면 된다는 것이다. 또한 주목할 것은 이 모든 표현이 한줄의 문장으로 이뤄졌다는 것이다. 즉 이런 표현이 쿼리 표현식 내에 표현될 수 있는 가능성이 확보된 것이다. 그런 의미에서 다시 한번 더 쿼리 표현식을 보자.

var query =

    from c in customers

    where c.Discount > 3

    orderby c.Discount

    select new { c.Name, Perc = c.Discount / 100 };

select 이하에서 익명 타입을 사용한 표현이 있다는 것을 알 수 있다. ^^

휴~~이제 거의 다 온 건가. 이제 마지막으로 람다 표현식에 대해서 알아보자.