C# 3.0 Preview: Extension Method와 나머지

이번 아티클에서 다루고자 하는 C# 3.0의 새로운 사양 역시도 매우 파격적이다. JavaScript 프로그래밍 언어의 장점(?)을 수용한 새로운 사양이다. 바로 Extension Method가 그것이다. 참고로 JavaScript는 prototype이라고 불리우는 예약된 객체에 새로운 메서드를 정의하고 관리할 수 있다.

Extension Method도 파격적인 언어 사양인데, 기존에 존재하지 않았던 제 3자의 메서드를 동적으로 삽입하는 기술이다. 말 그대로 클래스 스펙에 새로운 메서드를 동적으로 추가할 수 있다는 뜻이다. 그렇다면 이것은 객체 지향 프로그래밍 언어 사양을 완전히 무너뜨리는 기술일까? 한 번 살펴보자.!

Extension Method가 사용된 사례를 보고 싶다면 IList<T> 인터페이스와 호환되는 객체 하나를 만들고 이 객체를 IList<T>로 형 변환하여 나타나는 멤버들 중에 Reverse 메서드를 불러보면 된다. 그러나 System.Linq 네임스페이스는 잠시 제거해보기로 하고 컴파일해보자. 결과가 어떨까?

컴파일은 당연히 실패한다. Reverse라는 메서드가 IList<T> 인터페이스와 부모 인터페이스들 모두에 존재하지 않기 때문이다. 하지만 방금전에 제거했던 System.Linq 네임스페이스를 이번에는 넣어보고 컴파일하자. 그러면 신기하게도 컴파일이 잘 이루어진다.

이것이 의미하는 바가 무엇일까? 진정으로 언어 사양을 깨뜨린 것일까? 다행히도 아니다. 만약 이런식으로 메서드를 아무렇게나 추가할 수 있었다고 한다면 참으로 심각한 일이다. 하지만 특정 네임스페이스 안에 정의된 내용을 포함할지 아니할지의 여부에 따라서 확장 기능을 부여할 수 있도록 하는 것이다.

그러면 이제 본격적으로 Extension Method를 정의하는 방법을 살펴보기로 하자.



using System;
using System.Text.RegularExpressions;


namespace OrcasDrive
{
    public static class StringRegexExtender
    {
        public static Regex ToRegex(this string strInstance, RegexOptions nOptions)
        {
            return new Regex(strInstance, nOptions);
        }


        public static Regex ToRegex(this string strInstance)
        {
            return StringRegexExtender.ToRegex(strInstance, RegexOptions.None);
        }

    }


    internal static class Program
    {
        static void Main(string[] args)
        {
            string strExp = “[0-9]+”;
            Regex oRegex = strExp.ToRegex();
            Console.WriteLine(oRegex.IsMatch(“73820”) ? “Number” : “Not Number”);
        }
    }
}


굵게 강조 표시한 코드들이 바로 Extension Method를 정의하고 사용하는 방법을 설명하는 부분들이다. 우선 Extension Method를 어떻게 정의했는지 살펴보자.

Extension Method는 우리가 일반적으로 정의하는 정적 함수와 사양이 완전히 같고 단 하나의 인수가 더 필요한 것과 반드시 정적 클래스 안에 정의되어있어야 한다는 두 가지 규칙이 추가된 것이 특징이다.

public static Regex ToRegex(this string strInstance)

this string strInstance라는 파라미터가 눈에 띈다. 이것이 바로 Extension Method를 선언하기 위한 컴파일러에게 통지하는 힌트이다. 여기서 this를 제거한다면 그냥 ToRegex 정적 메서드가 작동하기 위하여 필요한 인수로 작동할 것이다. 하지만 여기에 this 키워드를 추가하여 string 형식, 정확히 말하여 System.String 클래스에 대하여 확장 메서드로 추가할 것을 이야기하고 있는 것이다.

여기서 잠시 생각해 볼 것이 있는데, 이와 같이 Extension Method로 선언하지 않아도 이 함수는 기존의 방법대로 사용할 수 있을까? 답은 “그렇다”이다. 기존의 방법대로 사용하던 Extension Method 선언을 이용하여 편입하던 간에 String 클래스에 대하여 이 ToRegex 메서드가 가지는 입장은 완전히 같은 것이다. 다시 말해, String 클래스 안의 private, protected 멤버와 String 클래스가 정의된 mscorlib 어셈블리 안의 internal 멤버들에 대하여 이 메서드는 접근 권한이 없는 것이다. 역으로 이 ToRegex 메서드를 사용하는 다른 코드의 입장에서도 ToRegex에 대해 상대적으로 움직인다. 겉 모양이 파격적이라고 속까지 그런 것은 아니며 철저히 객체 지향 프로그래밍 언어의 기본을 지켜주고 있는 것이다.

이제 위와 같이 선언한 코드가 사용된 예를 살펴보자.


string strExp = “[0-9]+”;
Regex oRegex = strExp.ToRegex();
Console.WriteLIne(oRegex.IsMatch(“73820”) ? “Number” : “Not Number”);

아주 그럴듯하고 멋진 코드가 나왔다.

참고로 this 키워드를 붙일 수 있는 인수는 해당 Extension Method에 하나만 허용된다. 그리고 this 키워드가 붙을 인수는 반드시 함수의 제일 처음에 와야 한다는 강제가 따른다.

자동 프로퍼티는 C# 3.0에서 언어적으로 새롭게 추가된 기능으로 따로 멤버 변수를 선언하고 이것을 캡슐화하는 프로퍼티를 만드는 수고 없이 간단하게 자동화할 수 있는 기능이다. 다음이 그 사용 예이며 매우 간단하다.


public string AutoPropTest
{
  get; set;
}

위와 같이 선언하기만 하면 C# 3.0의 경우 다음과 같은 의미를 가진다.


public static AutoPropTest
{
   get { return this.m_strValue; }
   set { this.m_strValue = value; }
}

그리고 C# 3.0에서 마지막으로 살펴보고자 하는 기능인 익명 배열도 참 간단하다.

var obj = new [] { “test”, “test 2”, “test 3” };

익명 배열은 익명 형식과 마찬가지로 코드 상에서 형식을 미리 지정하지 않고 컴파일 타임때 형식을 결정하는 기술이다. 위의 코드에서는 string 인스턴스로만 구성된 1차원 배열을 지정하였으므로 실제로는 string[] 형식으로 치환된다. 익명 배열 원소 중에 상속 관계와 관련이 없거나 완전히 다른 형식의 원소가 하나 이상 포함되면 형식을 결정할 수 없다는 오류가 발생하게 된다.

이번 아티클을 기점으로 C# 3.0의 모든 새로운 기능들은 한 번씩 둘러볼 수 있었다. 아티클을 편집하는 현 시점에서 Visual Studio 2008이라는 정식 명칭을 가진 새 버전의 Visual Studio 제품 시리즈가 베타 2 버전으로 배포되고 있으니 언제든지 시험해볼 수 있다.

C# 3.0 Preview: Extension Method와 나머지”에 대한 2개의 생각

댓글 남기기