달력

03

« 2010/03 »

  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
  •  

때때로 작성한 메서드를 과연 어디서 호출하는지 알고 싶을 때가 있습니다.
동일한 어셈블리 내에서의 호출일 수 도 있겠지만, public으로 노출된 메서드라면 현재 어셈블리 외의 외부에서도 호출이 가능합니다.

이럴 때 현재 메서드를 어느 어셈블리에서 호출하였는지를 알 수 있는 방법이 있습니다.
이미 알고 계시는지는 모르겠지만, Assembly 클래스의 정적메서드인 GetCallingAssembly 메서드가 이 방법을 제공하고 있습니다.

더보기

저작자 표시 동일 조건 변경 허락
이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by WHiSTLE

지난번 알아보았던 자동구현 프로퍼티(Auto-Implemented Properties)는 그동안 개발자들을 귀찮게 하던 멤버변수와 멤버변수에 대한 엑세스를 지원하는 프로퍼티를 생성하는데 좀 더 간결하게 표현할 수 있도록 해는 것이었다면 이번에 볼 객체와 컬렉션에 대한 이니셜라이저(Object and Collection Initializer)는 객체 또는 컬렉션의 생성을 좀더 직관적으로 할 수 있도록 해줍니다.

C# 2.0까지 객체를 생성할때 객체내의 멤버들을 동적으로 초기화 시키기 위해서는 생성자의 매개변수를 사용하거나, 생성후 객체의 각 멤버에 대해서 직접 값을 할당해주는 방법을 사용하였습니다만, C# 3.0의 Object and Collection Initializer는 생성자의 선언없이도 생성과 동시에 해당 객체나 컬렉션에 대한 초기화가 가능해지는 것입니다. 실제 코드를 보면 쉽게 이해가 가능하실 겁니다.

[코드 1-1 : C# 3.0 이전의 객체 초기화]

    1 public class Customer

    2 {

    3     private int custKey;

    4     private string name;

    5     private string address;

    6 

    7     public int CustKey { get { return custKey; } }

    8     public string Name

    9     {

   10         get { return name; }

   11         set { name = value; }

   12     }

   13     public string Address

   14     {

   15         get { return address; }

   16         set { address = value; }

   17     }

   18 }

   19 

   20 public class Program

   21 {

   22     static void Main(string[] args)

   23     {

   24         Customer customer = new Customer();

   25         customer.Name = "오성민";

   26         customer.Address = "서울시 구로구";

   27     }

   28 }

위의 코드는 언제나 보던 일반적인 코드입니다. 객체를 생성한 후 해당 객체의 멤버에 값을 할당하는 것이죠. 이 코드를 Object and Collection Initializer를 이용한 코드로 바꾼다면 아래와 같이 됩니다.

[코드 1-2 : C# 3.0 의 Object and Collection Initializer를 이용한 초기화

    1 public class Customer

    2 {

    3     public int CustKey { get; private set; }

    4     public string Name { get; set; }

    5     public string Address { get; set; }

    6 }

    7 

    8 public class Program

    9 {

   10     static void Main(string[] args)

   11     {

   12         Customer customer = new Customer

   13         {

   14             Name = "노휘겸",

   15             Address = "서울시 관악구"

   16         };

   17     }

   18 }

지난번에 보았던 자동구현 프로퍼티를 이용하여 Customer 클래스를 작성하였고, 이 클래스의 객체를 생성하는 시점에서 Customer객체의 내부 멤버들의 값을 할당하였습니다.

Object and Collection Initializer의 구성은 여러개의 멤버에 대한 이니셜라이저가 ,(콤마)로 구분되어 있으며, 이니셜라이저 외부에는 "{", "}"로 둘러싸여 구성되어 있습니다.
이니셜라이저는 접근이 가능한 멤버나 프로퍼티에 대해서만 값의 할당이 가능합니다.
즉, 위의 코드에서 본다면 set이 private 으로 구성된 CustKey의 경우에는 CustKey = 1 로 할당 할 수 없는 것입니다.
그리고, 한번에 같은 멤버를 두번이상 할당할 시에는 오류가 발생하게 됩니다.

아래는 위보다 조금 복잡한 사용예입니다.

[코드2]

    1 public class Point

    2 {

    3     public int X { get; set; }

    4     public int Y { get; set; }

    5 }

    6 

    7 public class Line

    8 {

    9     public Point P1 { get; set; }

   10     public Point P2 { get; set; }

   11 }

   12 

   13 public class Triangle

   14 {

   15     private Point p1 = new Point();

   16     private Point p2 = new Point();

   17     private Point p3 = new Point();

   18 

   19     public Point P1 { get { return p1; } set { p1 = value; } }

   20     public Point P2 { get { return p2; } set { p2 = value; } }

   21     public Point P3 { get { return p3; } set { p3 = value; } }

   22 }

   23 

   24 public class Program

   25 {

   26     static void Main(string[] args)

   27     {

   28         Line line = new Line

   29         {

   30             P1 = new Point { X = 1, Y = 1 },

   31             P2 = new Point { X = 4, Y = 4 }

   32         };

   33 

   34         Triangle triangle = new Triangle

   35         {

   36             P1 = { X = 0, Y = 0 },

   37             P2 = { X = 5, Y = 5 },

   38             P3 = { X = 5, Y = 0 }

   39         };

   40     }

   41 }

위와 같이 이니셜라이저 안에서 또다른 객체의 이니셜라이저가 존재할 수도 있으며, 이미 생성된 객체의 경우에는 값의 할당이 바로 이루어질 수도 있습니다.
line 객체의 경우 P1, P2 Point 객체가 생성되지 않았으므로 new Point {...}으로 생성과 함께 할당을 하였으나, triangle 객체의 경우에는 이미 Point 클래스의 객체들이 이미 생성되어 있으므로 생성하는 부분을 생략하고 바로 값을 할당하고 있음을 볼 수 있습니다.

만일 [코드1-2]에서와 같이 CustKey처럼 외부에서 할당이 불가능하고 생성자의 파라미터를 통해서 값을 할당해야 할때도 사용이 가능할까요?
물론 사용이 가능합니다. 생성자가 있다고 해서 달라질것은 생성자에 파라미터에 해당하는 값을 전송하면 되는 것이죠.

public class Customer

{

    public int CustKey { get; private set; }

    public string Name { get; set; }

    public string Address { get; set; }


    public Customer(int custKey)

    {

        CustKey = custKey;

    }

}


Customer customer = new Customer(1) { Name = "노휘겸", Address = "서울" };


만일 생성자에서 값이 할당된 멤버를 다시 이니셜라이저에서 값을 할당하면 이니셜라이저에서 할당한 값으로 설정이 됩니다.

이름이 Object and Collection Initializer 이므로 이제 컬렉션을 이용하는 코드를 보도록 하죠. 다들 예상하시겠지만, Collection이라고 해서 다른게 없이 위의 이니셜라이저 안에서 또 다른 이니셜라이저를 사용하는 것과 동일합니다.

    1 List<Customer> customers = new List<Customer>

    2 {

    3     new Customer(1) { Name = "노휘겸", Address = "서울" },

    4     new Customer(2) { Name = "류순필", Address = "마산" },

    5     new Customer(3) { Name = "황원준", Address = "오산" }

    6 };

Customer객체가 담기는 Generic List의 생성을 한번에 완료시켰습니다. 만일 이 코드를 C# 2.0의 코드로 작성한다면

    1 List<Customer> customers = new List<Customer>();

    2 Customer customer1 = new Customer(1);

    3 customer1.Name = "노휘겸";

    4 customer1.Address = "서울";

    5 customers.Add(customer1);

    6 ......

위와 같은 형태가 되겠죠? 보시는 여러분들이 판단하실 부분이긴 하지만, 제 주관적으로는 상당히 직관적이고 코드 읽기가 수월할 듯 하네요.

지난번 Auto-Implemented Properties 와 이번의 Object and Collection Initializer 의 경우 감탄을 자아낼 만큼 대단한 기능은 아니지만, C#의 언어의 표현력을 향상시켜주는 것 같습니다.

궁금한점이나 지적사항이 있으면 댓글로 남겨주세요.

크리에이티브 커먼즈 라이선스
Creative Commons License
TAG C# 3.0
Posted by WHiSTLE

Microsoft Patner 교육엘 다녀왔습니다. 처음 .NET을 접했을때 교육해주셨던 선생님이 Microsoft로 직장을 옮기셨는데, 이번 교육을 직접 진행하신다고 하길때 반가운 마음에 달려갔습니다.

교육은 Visual Studio 2008에 포함될 C# 3.0의 언어적인 발전부분에 대해서 Hands On Lab방식의 실습으로 이루어졌습니다. 사실 그동안 C# 3.0의 언어적인 발전부분에 대해서는 어느정도 관심은 있었지만, 게으른 관계로 깊이 공부해보지는 못했던 터라, 뜬 구름잡듯이만 알고 있었는데. 이번 교육을 통해서 개념을 잡을 수 있었던것 같습니다.

C# 3.0의 변화의 가장 핵심은 바로 Lambda Expression(람다식)의 지원이라고 할 수 있었습니다. 람다식을 지원하기 위해서 컴파일 타임의 형에 대한 추론능력이 비약적으로 발전하게 되었고, 그러한 타입에 대한 추론능력을 바탕으로 암시적 로컬 변수(Implicitly typed local variable) 및 익명타입(Anonymous Type)의 사용이 가능하게 되었으며, 개체와 컬렉션 이니셜라이저(Object and Collection Initializer)등으로 좀더 표현력이 뛰어난 언어로 발전할 수 있었던 것 같습니다.

그리고, 람다식이 가능하게 되므로서 C#언어 자체에서 데이터에 대한 SQL과 같은 구조적 질의또한 가능하게 되어 데이터의 활용이 한층 쉽고 강력해 진것도 느낄수 있더군요.

자동 구현 프로퍼티(Auto-Implemented Properties)

객체지향의 원칙중 캡슐화(Encapsulation)을 위하여 C#에서는 Property를 지원합니다. 하지만, 개발시에 private 접근자의 멤버변수와 이를 캡슐화하는 Property을 만들때 멤버변수로 접근하는 코드를 제외한 프로그래밍적인 처리가 들어가는 경우는 크게 많지 않습니다

private string name;

public string Name

{

    get { return name; }

    set { name = value; }

}

변수를 선언할때 위와 같이 거의 습관적으로 코딩하시는 분이 많을 겁니다. 저또한 거의 습관적으로 나오는 코드이고, 양이 많을 경우 매번 프로퍼티를 구현하는게 귀찮을 때도 많습니다. 물론 코드조각을 이용하시는 분들도 계시긴 하겠지만 저는 변수선언과 프로퍼티선언의 영역을 달리 하는 편이라 그것도 썩 맘에 들지 않아 그냥 손으로 코딩을 해버립니다.
물론 어쩔땐 get; set; 모두 노출해야 하는 멤버변수는 그냥 public으로 선언할 때도 있습니다.(-_-)

C# 3.0에서는 이러한 불필요한 듯한 노력을 줄여주는 자동 구현 프로퍼티가 반영되어 예전처럼 멤버변수와 프로퍼티의 구현을 기계적으로 할 필요가 없어졌습니다.
구문은 아래와 같습니다.

public string Name { get; set; }

public string Address { get; internal set; }

public string UserKey { get; private set; }

인터페이스에서 프로퍼티를 선언할 때와 거의 비슷한 구문을 가지고 있습니다만, 이는 인터페이스내에서 작성하는 코드가 아니라 클래스내에서 멤버변수의 선언과 프로퍼티의 선언을 한번에 해결할 수 있는 코드입니다.
하지만, 먼가 좀 이상하지 않으신가요? 프로퍼티란 메서드의 한 종류일뿐 분명히 변수는 아님에도 저게 어떻게 동작이 가능할까요? VB(.NET버전 이하)처럼 모든것을 포용해주는(가끔 프로그래머를 패닉상태로 몰고가기도 하죠.^^) C#이 아니지 않습니까? 깐깐한 C#이 변수도 선언하지 않았는데 메모리를 할당해 줄리는 만무 할텐데...
그것은 자동 구현 프로퍼티가 있으면 컴파일 타임에서 컴파일러가 멤버변수를 자동으로 생성해주게 되는 것입니다. 즉, 변수가 존재하지 않는게 아니라, 프로그래머가 해야할 일을 컴파일러가 대신해주는 것 뿐인거죠.

코드를 보시면 get; set;에 대하여 엑세스제한자를 지정할 수 있습니다. set에다 private를 지정할 수 있으므로 외부에서 값을 변경하는 것을 막을 수 있습니다.
하지만, 만일 set을 지정하지 않으면 내부에서 해당 변수에 접근이 불가능하기 때문에 get과 set 모두 존재해야지만 정상적인 사용이 가능합니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
TAG C# 3.0
Posted by WHiSTLE