.NET Framework 2.0에서 새롭게 추가된 부분은 매우 많습니다. 제일 잘 한 부분이라고 느껴지는 것은 제네릭 관련 부분입니다. 하지만 제네릭 못지 않게 편리해진 부분이 더 있는데 바로 Nullable Type과 Yield 키워드에 대한 사항입니다.

Nullable Type이란?

Nullable Type은 System.ValueType에 대해 보완 관계를 완성하는 일종의 보조 도구입니다. 사실 Nullable Type이라는 이름을 사용하지 않았을 뿐 이와 같은 일을 우리는 관습적으로 익혀왔습니다. 바로 System.Object로 형변환하는 작업을 일컬어 Boxing과 Unboxing을 하였다고 이야기했으며, 알고 계시다시피 System.Object로 Boxing을 할 경우 그 안에 들어있는 것이 Null 참조일 수도 있었습니다.

하지만 Nullable Type은 단지 System.Object로 Boxing하는 것보다 한 단계 더 앞의 것입니다. 단지 Null 참조를 대입할 수 만 있는 것이라면 Null 값이 아닌 경우를 좀 더 매끄럽게 핸들링하기 위해서 해줘야 할 일이 부수적으로 많았습니다. (물론, 아이디어를 짜 내어 간단한 메서드를 활용해서 Null 값이 들어있는 Object형의 경우 기본 값을 받아서 다시 반환하는 식의 디자인 패턴도 사용하곤 했습니다만.)

System.Nullable<T> 라는 좀 특별한 구조체를 통하여 이것을 가능하게 합니다. 눈치 빠르신 분들은 예상하셨겠지만 T는 Generic Parameter입니다. 물론 ValueType에 대한 것만을 다룰 것이기에 당연히 T는 where T: struct 라는 제약이 걸려있을 것도 예측할 수 있을 것입니다. (where 절에서 struct라는 것을 지정해야 ValueType을 가리키는 것으로 의미가 통한다는 것은 Generic을 써보신 분은 아실 것입니다.)

System.Nullable<T>의 멤버들을 살펴보면 재미있는 것이 있습니다. 우선 이 구조체의 생성자를 보면 구조체이기 때문에 미리 정의된 받을 인자가 없는 기본 생성자와 ValueType의 값을 하나 받도록 되어있는 생성자 버전 두 가지입니다. 인자 없이 그냥 생성자를 호출하는 경우 이것은 null 참조를 대입한 것과 동일하게 다루어집니다. 하지만 어떤 값을 줄 경우에는 null 값이 아니라 구체적인 값이 있는 것으로 다루어집니다. 이것을 구분하는 멤버가 HasValue 프로퍼티입니다.

그럼 System.Nullable<T>에서 값을 가져오는 방법은 무엇일까요? 막바로 보이는 Value 멤버의 getter 메서드를 호출하는 방법이 있습니다. 하지만 여기에는 규칙이 있는데, HasValue 프로퍼티의 값이 false로 나오는 경우는 여기에 Null 값을 대입한 것과 동일한 상태를 의미합니다. 이러한 경우 Value의 값 대신 예외가 Throw됩니다. 만약 값이 존재한다면 그 값이 정확히 반환될 것입니다.

그렇다면 값을 얻기 위해서 꼭 위와 같은 방법으로 접근하기 위해서 try - catch 구문을 써야할까요? 물론 아닙니다. 다른 메서드를 살펴보도록 하죠. 바로 GetValueOrDefault 메서드입니다. 이 메서드는 HasValue의 값이 무엇이든 가리지는 않습니다. 이 메서드는 또 다시 두 가지 버전으로 재정의되어있는 것을 보실 수 있습니다. T에서 지정한 형식의 인수를 받는 버전과 그냥 호출하는 버전의 차이입니다.

T에서 지정한 형식의 인수를 받는 버전의 경우 HasValue가 False로 나타날 경우 받았던 인수를 다시 반환합니다. 이것이 의미하는 것은 사실 간단합니다. 어떤 값도 아니고 의미없는 값을 넣었다면 이것을 구분할 수 있는 지역적인 수준의 코드 값이 되는 것입니다. 반면 인수를 받지 않는 버전의 경우 Generic에서 사용하는 문법적 기능 중 기본 값 반환에 의거하여 값을 반환합니다. 만약 int 형식으로 형식 인수 T를 지정했다면 컴파일러의 판단에 의하여 0을 반환할 것입니다. 0이라는 값을 넣은 경우와는 구분이 되지 않기 때문에 HasValue 프로퍼티를 검사해야 논리적인 오류를 피할 수 있을 것입니다.

Nullable Type을 사용하시면서 아셔야 할 특별한 제약 조건이 하나 있습니다. 다른 것은 아니며 Nullable Type은 그 자신을 다시 포함할 수 없다는 점입니다. 즉, 재귀적으로 Nullable Type을 쌓아올릴 수는 없음을 뜻합니다. 이 점만 유의하시면 어려운 점은 없을 것입니다.

Nullable Type 그 자체는 사실 누군가 만들어도 만들만한 물건입니다. 하지만 Nullable Type의 진가는 C#의 경우 다음 두 가지 문법적인 기능으로 발휘됩니다.

? 심벌: ValueType 형식명 뒤에 붙여줌으로서 Nullable<형식명> 표기를 줄입니다. 그리고 한 단계 더 나아가 하나의 독립적인 형식명으로서 인정되며 = null의 대입을 가능하게 합니다.

다음은 예제 코드입니다.

int? n = 123;
n += (int?)1;

int 형식과 호환성이 있지만 int? 라는 형식이 새로 생성된 것으로 이해하더라도 무방합니다. (사실 Generic에 인수를 대입한다는 사실이 그런 모양이기는 합니다.) 당연히 저 코드가 실행된 후의 n의 내부 값은 124가 될 것입니다.

?? 연산자: ?? 연산자는 결론부터 말씀드리면 이전 버전에서 수행하던 다음의 코드를 축약한 것입니다. (m_testObject가 ValueType이 아닐 경우를 예로 들어봤습니다.)

if(m_testObject == null)
  m_testObject = new object();

// 위의 코드를 이제는 한 줄이면 씁니다.
m_testObject = m_testObject ?? new object();

눈치가 빠르신 분들은 짐작하셨겠지만 ?? 연산자가 의미하는 조건문은 ?? 연산자의 앞에 오는 조건식 또는 인스턴스가 null 참조일 경우 ?? 다음에 오는 조건식 또는 인스턴스를 실행하는 것입니다. ValueType이 아닐 경우에 쓰이기도 하지만 위의 코드는 Nullable Type에 대해서도 유효하다는 사실에 주목할 필요가 있습니다.

Nullable Type에 대한 이야기는 여기서 간단히 마치도록 하고 이번엔 Yield 키워드에 대해서 살펴보도록 하겠습니다.

Yield 키워드란?

미리 중요한 힌트를 말씀드리면 Yield 키워드는 System.IEnumerable과 관련이 있으며 foreach와도 밀접하게 관련되어있습니다. 바로 반복에 관한 기능을 문법적으로 포장한 것입니다. 어려워 보이고 복잡해 보이는 기능일 수 있지만 잘 활용하면 컬렉션을 선택적으로 만드는 데에 있어서 자칫 복잡해 질 수 있는 코드를 깔끔하게 정리하는 데 일조를 하도록 할 수 있습니다.

다음의 코드를 살펴보면서 간단히 yield return과 yield break의 기능을 살펴보도록 하겠습니다.

using System;
using System.Collections.Generic;

public static class Program
{
  public static IEnumerable<string> GetMessages()
  {
   yield return "H";
   yield return "ello";
   yield return " ";
   yield return "W";
   yield return "orld";
   yield return "!";
   yield return Environment.NewLine;
   yield break;
  }

  [MTAThread()]
  public static int Main(string[] arguments)
  {
   foreach(string eachString in GetMessages())
      Console.Write(eachString);

   return 0;
  }
}

코드를 실행해 보시면 아시겠지만 yield return은 그냥 return을 쓰는 것과는 다르게 "쌓아둔다"라는 느낌을 느낄 수 있습니다. 짐작하신 그대로 코드를 실행해보면 yield return 문으로 기록해 놓은 문자열들이 그대로 IEnumerable<string> 형식으로 반환되어 콘솔에 Hello World! 라는 문자열로 나타나는 것을 볼 수 있습니다. 그렇다면 yield break 문은 당연히 쌓아놓은 yield return 문의 데이터들을 한꺼번에 컬렉션으로 변환시켜 문을 종료하는 것으로 이해할 수 있습니다.

yield 키워드를 사용하여 컬렉션을 만들기 위해서는 물론 IEnumerable 또는 IEnumerable<T> 형식으로 반환해야 한다는 조건이 붙으며 한 가지 제약이 더 붙습니다. .NET 2.0에서 새로 추가된 것 중 익명 메서드 안에서는 위와 같이 yield 키워드를 사용할 수 없다는 점입니다.

ps. 태터툴즈 클래식에서는 제네릭이라는 것을 표기하기 위해서 반드시 HTML 엔티티로 꺽쇠 기호를 나타내야 하는군요. ^^;

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

Mono 1.1.x 빌드에서 C# 2.0 문법을 사용하기 위해서는 "반드시" 참고하셔야 합니다. mcs 컴파일러는 C# 1.x 문법을 다루는 컴파일러입니다. 당연히 아래의 세 강좌를 mcs 컴파일러로 구동하려고 한다면 오류를 만납니다. gmcs 컴파일러를 사용하여 컴파일하셔야 합니다.

Mono 1.1.x 빌드는 Microsoft .NET Framework 2.x와 마찬가지로 ASP .NET 2.0을 지원합니다. ASP .NET 2.0에 관한 간단한 기능 시험을 해보시려면 우선 XSP 웹 서버로 테스트해보시길 권장하고 싶습니다. ASP .NET 1.x 만을 지원하는 웹 서버는 xsp 이며, ASP .NET 2.0까지 지원하는 웹 서버는 xsp2 입니다.

최신 기술에 대한 개념 이해는 Visual Studio 2005를 활용해보시는 것이 좋을 것이라 권장하고 싶습니다. Visual Studio 2005의 무료 버전인 Express Edition 버전이 MSDN에서 배포중이니 Windows 플랫폼에서 한번 사용해 보십시오. 인터넷을 통하여 다운로드하므로 프록시에 대한 설정이 필요할 수 있고 시간이 오래 걸릴 수 있습니다. 전화 접속 모뎀에서는 권장하지 않습니다.

Visual Studio 2005 Express Edition 다운로드 페이지

http://msdn.microsoft.com/express/

좋은 하루 되십시오. ^^

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

C# 2.0은 지금 소개하는 Generic이라는 기술을 통하여 Object 형식을 다루는 방법을 새롭게 제공합니다. 더 이상 복잡한 조건문을 메서드 안에 배열할 필요가 없으며 이 개념을 통하여 새로운 디자인 패턴을 만들 수 있게 되었습니다. 이 글을 작성하는 현 시점에서는 아직까지 Generic의 정확한 번역 용어가 채택되지 않았으므로 원래의 뜻을 유지하기 위하여 Generic으로 표기하고 있으므로 양해 바랍니다.

1. Generic 클래스의 문법 구조
Generic 클래스를 선언하는 방법은 기존의 클래스와 유사합니다. 하지만 기존의 클래스 선언에는 없는 몇 가지 추가 구문이 명시되어야만 합니다. C# 구문을 기준으로 설명하도록 하지요.

Visual Studio 개발자 여러분들을 위한 안내: Visual Basic .NET, J#, Visual C++, JScript .NET 및 기타 언어를 사용중이신 프로그래머분들께서는 MSDN Library 베타를 참조하십시오. J#에서 이 Generic을 사용할 경우 기존의 Java, J++, J# 1.x 문법과 호환되지 않는다는 점을 꼭 염두에 두시기 바랍니다. Visual C++ 8.x 버전의 컴파일러에서 Managed Extensions for C++의 키워드가 새롭게 바뀌었습니다. 그에 따라, Managed Extensions for C++ 1.x 버전으로 작성된 소스 코드에 대한 업데이트 또는 유지 보수가 필요할 것으로 예상됩니다. 그리고 이번 업데이트를 기준으로 하여 C++의 Template과도 일정 부분은 연동이 가능할 것으로 예상됩니다. (일부 형식 제한 지정과 같은 문법은 표준에 어긋나므로 주의하십시오.)

[public | private | internal | ...] [sealed | abstract] class [Class Name]
      <[Argument Type I], [Argument Type II], ..., [ArgumentType n]> : [Parent Class], [Interface I], ...
{
  // Class Body
}

클래스의 이름과 상속 관계를 지정하는 영역 사이에 부등식 기호 '<', '>' 안에 사용자 정의 형식을 지정합니다. 이 사용자 정의 형식은 임의로 이름을 붙일 수 있으나 클래스 이름의 명명법을 그대로 따르므로 클래스 이름의 명명법에 어긋나는 형태의 이름은 사용할 수 없습니다.

Generic 인수에는 단순히 클래스 형식을 지정할 수도 있지만, 구조체 형식, 인터페이스 형식, 대리자 형식, 중첩 Generic 형식의 지정도 가능합니다. 다시 말해, 사용하기에 따라서는 이 Generic 인수 자체가 복잡한 인수 트리 구조를 생성할 수도 있다는 뜻입니다. 하지만 한 세대 이상 파고드는 예는 그리 많지 않으므로 어렵게 생각하실 필요는 없습니다.

이 강좌를 처음 접하시는 프로그래머 분들 중에는 비교적 근래에 C++에서 도입된 개념인 Template을 떠올리신 분들도 계시리라 생각됩니다. 예상하신 그대로, Generic은 C++의 Template를 C#에 맞게 첨삭한 클론입니다. 하지만 Template에는 없거나 다소 불편한 개념을 수정한 것이 .NET 플랫폼의 Generic의 특징이라고 할 수 있습니다.

2. Generic 클래스에서의 사용자 정의 형식 활용 방법
Generic 클래스 안에서 사용자 정의 형식을 활용하시는 방법은 단순합니다. 사용자 정의 형식은 사실 System.Object 형식을 상속한 것과 다를 바가 없습니다. 그리고 Generic 클래스 인수 안에서 명시된 적이 있는 사용자 정의 형식은 중첩된 서브 클래스에서도 유효합니다.

3. Generic 클래스의 인스턴스 만들기
다음의 예제 코드를 살펴보도록 하지요.

using System;

namespace Test2
{
  public class Generic1 <FirstType> : System.MarshalByRefObject
  {
       private FirstType m_firstType;

      public Generic1(FirstType firstType)
       {
           this.m_firstType = firstType;
       }

      public FirstType FirstTypeInstance
       {
           get
           {
               return this.m_firstType;
           }
       }

      public override int GetHashCode()
       {
           return this.m_firstType.GetHashCode();
       }

      public override string ToString()
       {
           return this.m_firstType.ToString();
       }
  }

  public sealed class MainObject
  {
       [MTAThread()]
       public static void Main(string[] arguments)
       {
           Generic1<string> s = new Generic1<string> ("Test");
           Console.WriteLine("{0}", s);
           Console.ReadLine();
       }
  }
}

Generic이 지정된 클래스는 형식 선언을 할 때 부터 인수를 지정되는 모습을 볼 수 있습니다. Generic1<string> 이라는 형식의 의미는 string (System.String) 형식만을 받아들이는 Generic1 클래스의 단편을 뜻합니다. 그리고 Generic1<string> 이라는 선언 자체는 하나의 형식 키워드가 되기 때문에 생성자를 호출할 때에도 다시 한번 Generic1<string> 이라는 이름을 사용하게 됩니다.

4. Generic 클래스의 상속
Generic 클래스의 상속에 관하여 새롭게 소개되는 용어가 하나 있습니다. 의미는 우리가 익히 알고 있으나 용어 자체는 새로울 것입니다. 기존의 클래스를 C# 2.0에서는 Concrete 클래스라고 새롭게 명명하였는데, 상속 관계를 설명할 때에는 반드시 알아두셔야 하는 개념입니다.

Generic 클래스의 특성을 유지하면서 상속을 할 수 있을 때에는 자식 클래스도 Generic 클래스로 인정됩니다. 하지만 Generic 클래스의 특성을 유지할 수 없는 상속을 하여 Generic 클래스의 특성을 소멸시킨 상속을 한 자식 클래스는 Concrete 클래스로 취급됩니다. 봉인된 Concrete 클래스가 아닐 경우 얼마든지 새로운 상속 관계를 형성할 수는 있지만 부모에 관한 모든 Generic 정보에 대한 접근 권한은 잃어버립니다.

4.1. Generic 클래스의 인수를 줄이는 상속
다음의 구문을 살펴보도록 합시다.

public class Parent1 <A, B, C> { ... }
public class Child1 <A, B> : Parent1 <A, B, int> { ... }

어떻습니까? Child1 클래스에서는 A와 B 형식만을 받아들이도록 되어있지만 Parent1 클래스의 형식 인자 목록을 충족하도록 선언하였습니다. 이것이 Generic 클래스의 인수를 줄이는 상속의 한 예입니다. 여기서는 특정 위치에 있는 하나의 인수를 제거하였지만, 원하는 위치에 원하는 수 만큼의 인수를 제거할 수 있습니다.

4.2. Generic 클래스의 인수를 늘이는 상속
다음의 구문을 살펴보도록 합시다.

public class Parent2 <A, B, C> { ... }
public class Child2 <A, B, C, D> : Parent2 <A, B, D> { /* 인수 C를 활용하는 코드 */ }

4.1 섹션과 마찬가지로 Parent2의 인수 목록을 Child2가 모두 만족하는 상속을 하였습니다. 남아있는 C 형식에 관한 활용에만 집중하면 Child2 클래스의 작업은 끝이 나는 것입니다.

4.3. Generic 클래스의 인수를 유지하는 상속
다음의 구문을 살펴보도록 합시다.

public class Parent3 <A, B, C> { ... }
public class Child3 <AChild, BChild, CChild> : Parent3 <AChild, BChild, CChild> { ... }

인수의 이름이 달라지더라도 이상이 없음을 보여주는 예제였습니다.

4.4. Generic 클래스의 관계를 끊는 Concrete 클래스
다음의 구문을 살펴보도록 합시다.

public class Parent4 <A, B, C> { ... }
public class Child4 : Parent4 <short, int, long> { ... }

Child4는 클래스 자체에 대한 상속은 제공하고 있지만 Generic에 관한 특성을 완전히 소멸시킨 것입니다. Child4 클래스가 만약 봉인된 클래스라면 Generic에 관한 측면은 물론 클래스 자체에 대한 상속마저도 봉인한 고립된 클래스가 됩니다.

4.5. Concrete 클래스로부터 새로운 Generic 관계를 생성하기
다음의 구문을 살펴보도록 합시다.

public class Parent5 <A, B, C> : System.MarshalByRefObject { ... }

System.MarshalByRefObject 클래스 자체는 봉인 클래스가 아니기 때문에 새로운 Generic 관계의 생성을 허용한 것이 되었습니다. 만약 System.MarshalByRefObject 클래스가 봉인 클래스였다면 위의 구문은 오류를 유발할 것입니다.

오늘 강좌는 Generic 클래스에 대한 것들을 살펴보았습니다. 다음회 강좌에서는 Generic 인터페이스에 대해서 살펴보도록 하겠습니다. 미리 말씀드리는 부분이지만 Generic 인터페이스의 상속도 섹션 4의 내용을 그대로 적용하므로 이 부분에 관한 충분한 실습을 통하여 감각을 익혀두시기를 권장합니다.

좋은 하루 되십시오. ^^

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

이제까지 대리자의 선언은 명시적인 대리자 선언이 많이 사용되어왔습니다. 하지만 C# 2.0에서는 새롭게 추가된 대리자 프로그래밍 방법론을 제공합니다. 바로 익명 대리자 혹은 인라인 대리자라고 합니다. 이 기술을 이용하여 특정 메서드나 코드 블럭 안에서 간단히 새로운 메서드를 작성하는 것이 가능해졌습니다.

이 익명 대리자를 사용하는 조건은 기존의 명시적인 대리자 선언과 마찬가지로 대리자 형식의 선언이 되어있어야 한다는 전제가 깔려있습니다. 하지만 구현 방법과 시점의 차이가 명시적인 대리자와 익명 대리자를 구분하는 기준선이 되는 것입니다.

명시적인 대리자를 구현하는 클래스를 살펴보도록 하지요.

    // Common.cs

    using System;

    namespace Test

    {

      [Serializable()]

      public delegate void TestDelegate(int a, string b);

      public interface ITester

      {

           void Test();

      }

    }

    // NamedTest.cs

    using System;

    using Test;

    namespace Test.Named

    {

      public class NamedTest : ITester

      {

           public void Test()

           {

               TestDelegate d = new TestDelegate(this.NamedMethod);

               d(123, "named: one-two-three!");

           }

           private void NamedMethod(int a, string b)

           {

               Console.WriteLine(a.ToString());

               Console.WriteLine(b);

               Console.ReadLine();

           }

      }

    }

    // AnonTest.cs

    using System;

    using Test;

    namespace Test.Anon

    {

      public class AnonTest : ITester

      {

           public void Test()

           {

               TestDelegate d = delegate(int a, string b)

               {

                   Console.WriteLine(a.ToString());

                   Console.WriteLine(b);

                   Console.ReadLine();

               }; // 세미콜론은 필수!

               d(123, "anon: one-two-three!");

           }

      }

    }

    // MainObject.cs

    using System;

    using Test.Named;

    using Test.Anon;

    namespace Test

    {

      public sealed class MainObject

      {

           [MTAThread()]

           public static void Main(string[] arguments)

           {

               ITester t = new NamedTest();

               t.Test();

               t = new AnonTest();

               t.Test();

           }

      }

    }

개략적인 문법 사항만을 살펴보도록 하겠습니다. 지금 지적하는 부분 이외에는 기존의 대리자 프로그래밍 방법과 동일합니다.

익명 대리자를 지정하기 위하여 다음과 같은 구문을 사용합니다.

    delegate(매개변수 목록)

    {

      // 함수 본문;

    };

매개변수 목록은 해당 대리자의 인수 목록과 일치하도록 선언되어야만 합니다. 함수 본문은 메서드와 동일하게 작성할 수 있으며, return 키워드로 반환값을 반환할 수 있는 조건은 대리자의 반환값에 관한 시그니처에 따라서 달라집니다. 그리고 실수하지 말아야할 부분은 이 블럭이 끝나는 대괄호 끝에는 반드시 세미콜론을 기록해야 합니다.

다음 강좌에서는 클래스의 Generic에 관하여 살펴보도록 하겠습니다. 좋은 하루 되십시오.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

수시 1학기 원서 접수가 끝이나고 서류들을 다 붙이고 나니 비로소 시간이 많이 남는군요. 오랫만에 뵙겠습니다. Mono 1.1.8 이후 빌드가 충실하게 C# 2.0 스펙을 지원하고 있더군요. 모르고 있었습니다. 역시 고등학교 3학년으로서 살면 안되는 이유가 여기에 있구나 하는 생각이 절실히 들더군요.

Visual Studio 2005를 사용해 보신 분들도 계실겁니다. Express Edition (MSDN Lab에서 다운로드 받으실 수 있는 무료 트라이얼 버전)도 좋고 MSDN Connection으로 Full Beta Package를 우편으로 받으신 분들도 계실 것입니다. 하지만 문법 사항이 많이 달라지고 뭔가 난해해졌다는 느낌부터 받으셨을지 모르겠습니다.

이제부터 시리즈로 올라가는 이 강좌들은 달라진 C# 2.0 구문에 대해서 차근차근히 살펴보도록 하고자 합니다. 오늘 강좌는 partial 키워드에 대해서 알아보도록 합시다.

partial 키워드는 특히 ASP .NET 2.0의 페이지 객체 모델을 향상시키는데에 큰 공헌을 한 매우 중요한 키워드입니다. ASP .NET 1.x 버전들에서는 클래스 라이브러리 (.dll) 파일 안의 클래스를 .aspx 페이지의 클래스가 상속을 받는 방법을 사용했습니다. 이러하다 보니 매우 복잡한 상속 관계 양상을 띄게 되었습니다. Windows Forms 처럼 페이지 상속이 불가능한 이유도 여기에 있었습니다.

그러나 partial 키워드는 우리가 이제껏 상상해왔던 모델을 구현할 수 있도록 도와줍니다. 예를 들어보도록 하지요.

    // APart1.cs 파일의 내용입니다.

    public partial class A

    {

       private int m_int = 1;

    }

    // APart2.cs 파일의 내용입니다.

    public partial class A

    {

       public int IntegerValue

       {

           get { return this.m_int; }

           set { this.m_int = value; }

       }

    }

    // MainObject.cs 파일의 내용입니다.

    public class MainObject

    {

       [MTAThread()]

       public static void Main(string[] arguments)

       {

           A test = new A();

           Console.WriteLIne(test.IntegerValue);

           test.IntegerValue += 5;

           Console.WriteLine(test.IntegerValue);

           Console.ReadLine();

       }

    }

결과는 예상한 그대로 A 라는 클래스 하나가 완성되는 형태로 컴파일됩니다. ASP .NET 2.0은 이와 같은 원리로 하나의 페이지 클래스를 작성할 수 있도록 합니다. .aspx 페이지를 소스 코드로 번역하고, 사용자가 작성한 비하인드 코드를 컴파일러에 같이 전송하여 컴파일하는 것입니다.

이 partial 키워드의 사용 범위는 단일 어셈블리 안에서만 한정되므로 주의해야 합니다. 참조 관계에 있고 같은 네임스페이스 안이라고 할지라도 전혀 별개로 취급됩니다. 또 partial 키워드는 인터페이스, 구조체에도 적용이 가능하므로 유용하게 사용하실 수 있을것입니다.

다음 강좌에서는 익명 대리자 (Anonymous Delegate)에 관한 것들을 살펴보도록 하지요. 좋은 하루 되십시오. ^^

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)