노트: 이 아티클은 Microsoft Visual C# 컴파일러 버전 3.0을 기준으로 작성되었습니다. Mono C# 컴파일러에서는 아직 확인되지 않은 기능입니다.

Extension Method는 대체로 특정 형식과 함께 그 형식을 부모 형식으로 사용하는 다른 형식들에 일괄적으로 영향을 주도록 선언이 설정됩니다. 상속 관계에 있어서는 편리하게 사용할 수 있지만, 비슷한 인터페이스들을 하나 이상 동시에 구현하는 여러 종류의 형식을 선택하는 방법이 잘 보이지 않았습니다.

구현하고자 하는 인터페이스의 수가 늘어나게 되면 일정한 패턴을 형성하게 되는데, 이러한 패턴을 Generic에 대입하고, 이러한 형식 패턴에 대하여 Extension Method를 추가하는 방법을 이번 Article에서 소개하고자 합니다.

다음의 예제 코드를 살펴보기로 합니다.

public static class SpecialExtensions
{
    public static string SpecialMethod<T>(this T target)
        where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
    {
        return target.ToString();
    }
}

위의 코드에서 제네릭 형식 T는 where 절의 서술에 따라 다음의 조건을 만족해야 하는 특수성을 가지게 됩니다.

  • struct 키워드가 사용되었기 때문에 값 형식에 속해야 한다.
  • IComparable 인터페이스를 구현하고 있어야 한다.
  • IFormattable 인터페이스를 구현하고 있어야 한다.
  • IConvertible 인터페이스를 구현하고 있어야 한다.
  • IComparable<T> 인터페이스를 구현하고 있어야 한다. 이 때 SpecialMethod<T> 메서드의 인자 T를 그대로 전달하게 된다.
  • IEquatable<T> 인터페이스를 구현하고 있어야 한다. 이 때 SpecialMethod<T> 메서드의 인자 T를 그대로 전달하게 된다.

위의 where 절에서 언급한 이와 같은 인터페이스 구현 패턴은 Primitive Type에 대한 설정으로, 아래와 같이 작동여부가 선택적으로 바뀌게 됩니다. 즉, 구조체이거나 나열 상수라서 모두 SpecialMethod 메서드를 사용할 수 있는 것이 아니고 위의 인터페이스 구현 패턴을 따르는 Primitive Type에 대해서만 SpecialMethod 메서드의 호출이 허용되게 됩니다.

true.SpecialMethod(); // 실패: IFormattable 인터페이스가 구현되지 않음
char.MaxValue.SpecialMethod(); // 실패: IFormattable 인터페이스가 구현되지 않음
Guid.Empty.SpecialMethod(); // 실패: IConvertible 인터페이스가 구현되지 않음
UriFormat.SafeUnescaped.SpecialMethod(); // 실패: IComparable<T>, IEnumerable<T> 인터페이스가 구현되지 않음

byte.MaxValue.SpecialMethod(); // 성공
sbyte.MaxValue.SpecialMethod(); // 성공
short.MaxValue.SpecialMethod(); // 성공
ushort.MaxValue.SpecialMethod(); // 성공
int.MaxValue.SpecialMethod(); // 성공
uint.MaxValue.SpecialMethod(); // 성공
long.MaxValue.SpecialMethod(); // 성공
ulong.MaxValue.SpecialMethod(); // 성공
float.MaxValue.SpecialMethod(); // 성공
double.MaxValue.SpecialMethod(); // 성공
decimal.MaxValue.SpecialMethod(); // 성공

또 다른 방면으로 where 절의 특수 조건 절을 적절히 활용하면, 추상 클래스와 일반 클래스 사이를 선택하여 Extension Method가 달리 선언될 수 있도록 제어하는 것도 가능합니다. 이와 같이 상속 방향 이외의 진행 방향으로 다양하게 Extension Method의 지정 범위를 택하는 기술을 이용하면 좀 더 구체적이고 깊이있는 요구 사항을 처리할 수 있습니다.

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

Project Blend: xPlatform을 조금씩 차곡차곡 진행시켜 나가고 있는 중입니다. 그동안 다양한 방법으로 조사하고 코드를 테스트하고 디자인한 결과를 드디어 조금씩 실행에 옮기고 있습니다.

포인터에 관한 새로운 접근

using System;
using xPlatform;
using xPlatform.Strings;
using xPlatform.x86.msvcrt;

namespace xPlatform.Core.Test
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            const string targetString = "안녕하세요.";

            using (GlobalHeapAnsiString str = new GlobalHeapAnsiString(targetString))
            {
                size_t len = msvcrt.strlen(str.Address);
                Console.WriteLine("String: \"{0}\", ANSI Length: {1}", targetString, len);

                BytePointer ptr = new BytePointer(str.Address);

                for (size_t i = (size_t)0u; i < len; i++, ptr++)
                    Console.Write("{0} ", ptr.GetData().ToString());
            }

            Console.WriteLine();
            Console.WriteLine();

            using (GlobalHeapUnicodeString str = new GlobalHeapUnicodeString(targetString))
            {
                size_t len = msvcrt.wcslen(str.Address);
                Console.WriteLine("String: \"{0}\", Unicode Length: {1}", targetString, len);

                WideCharPointer ptr = new WideCharPointer(str.Address);

                for (size_t i = (size_t)0u; i < len; i++)
                    Console.Write("{0} ", (ptr + (int)i).GetData().ToString());
            }

            Console.WriteLine();
            Console.ReadLine();
        }
    }
}

기존에 Base Class Library만을 이용하여 포인터를 활용해서 프로그래밍하는 작업은 작성해야 하는 코드의 양도 많았고 실수하기도 쉬웠습니다. 이러한 단점을 보완하고 좀 더 실용적이고 직관적으로 포인터 프로그래밍을 수행할 수 있는 방법을 고심한 끝에 위와 같은 패턴의 코드를 구현하였습니다.

GlobalHeapAnsiString, GlobalHeapUnicodeString 등의 클래스

보통 닷넷의 문자열을 비관리 메모리 영역에 저장하기 위해서 Marshal 클래스의 StringToHGlobalAnsi 같은 메서드를 이용해서 처리하는 것이 보편적이었습니다. 그리고 FreeHGlobal 메서드로 해당 메모리 블럭을 소거해야 하는 일도 잊지 않아야 했습니다. 이러한 작업을 자동화하기 위하여 위와 같은 클래스를 디자인하였습니다. 권한에 관한 이슈를 해결하지 못하여 SafeHandle 기반의 상속 혜택을 구현하지는 못하고 있습니다만 곧 해결할 수 있을것으로 기대합니다. Dispose 메서드를 노출하지는 않고 있으나 IDisposable 인터페이스를 구현하도록 하였습니다.

BytePointer, WideCharPointer 등의 클래스

Base Class Library가 제공하는 IntPtr이나 UIntPtr은 C/C++의 void*나 LPVOID에 가까운 것입니다. 형식 정보가 없기 때문에 주소 탐색 기능을 이용할 수 없다는 한계가 존재하기 때문에 이를 보완하기 위하여 Marshal 클래스의 ReadByte, ReadInt32 같은 메서드나 WriteByte, WriteInt32 같은 메서드를 통해 오프셋을 지정하여 주소 탐색을 간접 처리하는 것이 전부였습니다. 그렇지만 xPlatform에서는 +, -, ++, --, ==, != 등의 포인터에 대해서 사용할 수 있는 주요 연산자를 정의하는 커스텀 포인터 구조체들을 대거 추가하였습니다. 향후 이 부분을 템플릿화하여 직접 만든 구조체나 나열 상수에 대한 포인터도 사용자 정의할 수 있게 만들 생각입니다.

size_t 등의 Native C 형식 지원

닷넷의 Enum 형식은 생각보다 씀씀이가 많습니다. 특히 Primitive Type 중 정수 계열 (int, uint, short, ushort, long, ulong 등)을 enum으로 재정의하여 C/C++이 원래 사용하던 size_t 같은 형식을 그대로 재현할 수 있었습니다. 문법적으로도 size_t와 uint 사이는 관련은 있지만 명시적 변환이 이루어져야만 하는 원래의 코드에서처럼 C#에서도 동일하게 동작합니다.

ptr++, (ptr + i) 등의 표현식 지원

주소 탐색을 위하여 더 이상 어렵고 복잡한 간접 우회 코드를 사용하지 마시고, 그냥 C/C++에서 하던 것처럼 원소 수를 더하거나 빼서 주소 탐색을 하시면 됩니다. :-)

향후 계획

코어 파트는 좀 더 개선할 부분이 많고 테스트가 많이 필요합니다. 많은 분들의 참여와 관심을 통하여 개선을 시켜 나가야 할 것으로 생각합니다. 그리고 더 나아가서는 C++ Name Mangling 등의 복잡한 이슈를 직접 풀고 C#에서 바로 C++ 코드를 액세스할 수 있게 만드는 작업도 욕심을 내보고 싶습니다.

프로젝트 홈페이지는 http://blendxplatform.codeplex.com 이며 누구나 체크아웃해가실 수 있습니다. 서브 버전, TFS 등을 이용하여 쉽게 받아가실 수 있습니다.

Subversion 주소: https://blendxplatform.svn.codeplex.com/svn
TFS 주소: https://tfs05.codeplex.com

 

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

닷넷 개발자를 위한, 닷넷 개발자에 의한, 닷넷 개발자의 닷넷커뮤니티 컨퍼런스

닷넷 개발자를 위한, 닷넷 개발자에 의한, 닷넷 개발자의 닷넷커뮤니티 컨퍼런스

닷넷 개발자를 위한, 닷넷 개발자에 의한, 닷넷 개발자의 닷넷커뮤니티 컨퍼런스

 

 


닷넷 개발자를 위한, 닷넷 개발자에 의한, 닷넷 개발자의 닷넷커뮤니티 컨퍼런스

닷넷 개발자를 위한, 닷넷 개발자에 의한, 닷넷 개발자의 닷넷커뮤니티 컨퍼런스


닷넷 개발자를 위한, 닷넷 개발자에 의한, 닷넷 개발자의 닷넷커뮤니티 컨퍼런스

 

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

긴 공백 기간 끝에 Mono와 MonoDevelop가 새 버전을 발표하였습니다. 날이 갈수록 좋아지고 발전하는 프레임워크와 개발 도구를 바탕으로 닷넷 기술을 좀 더 범용적으로 활용할 수 있게 되지 않을까 기대됩니다.

Mono 2.4에서는 Mono 2.2 이후로 수집된 수많은 버그와 문제점을 교정하는 일을 게을리 하지 않았으며, 좀 더 상용 어플리케이션의 호스팅에 알맞는 환경을 구현하기 위하여 성능을 개선하는데에 초점을 맞추고 있습니다.

Mono 2.4의 주요 변경 사항들은 다음과 같이 요약 가능합니다.

  • SIMD (Single Instruction Multiple Data) 기반의 고속 배열 연산을 최적화하고 디자인 가이드 라인을 준수하도록 업데이트하였습니다.
  • 다중 스레드 작업 시 Thread.Interrupt() 메서드에 관한 기능이 향상되었습니다.
  • 기존 JIT (Just In Time) 엔진에서 선형 IR 기반 JIT 엔진으로 완전히 변경하였습니다.
  • 환경 설정 옵션 중 --enable-parallel-mark=yes 항목이 기본으로 포함되어있어 다중 코어 프로세서 시스템에서는 이전보다 더욱 개선된 Garbage Collection 성능을 발휘합니다.
  • WaitHandle에서 SignalAndWait 메서드를 지원합니다.
  • MarshalByRefObject에서 MemberwiseClone 메서드를 지원합니다.
  • COM 상호 운용성에서 IDispatch와 IUnknown에 대한 NULL 처리를 지원합니다.
  • System.Diagnostic.Process 클래스의 OutputDataReceived, ErrorDataReceived 이벤트에 관한 동작을 개선하여 제대로 동작하도록 수정하였습니다.
  • Mono.Posix의 경우 실시간 신호 (Real Time Signal)를 지원할 수 있게 개선되었습니다.
  • 새로 개선된 XPath 구현을 Mono 프로젝트의 자체 테스트 결과로 테스트해본 결과 이전 대비 15% 정도 메모리 사용량이 감소하였습니다.
  • DateTime.TryParse 메서드의 오류 처리를 개선하였습니다.
  • 위성 어셈블리에서 다국어 리소스를 로드하는 과정에서 내부적으로 예외를 던지는 동작을 하지 않습니다.
  • ASP.NET의 출판 기능과 동일한 기능을 하는 명령줄 도구인 aspnet_compiler가 추가되었습니다. GUI에 연결된 형태는 아니나 이를 기초로 Visual Studio의 출판 기능과 동일하게 만들 수 있게 되었습니다.
  • xsp나 mod_mono에 단일 어플리케이션만 구동되도록 설정되어있을 경우 이전보다 더 빠르고 효율적으로 동작합니다. 내부적으로 Multiplexor와 Demultiplexor, 리모팅에 관한 호출을 줄이도록 개선되었습니다.
  • Windows Forms의 경우 DataGridView의 데이터 바인딩에 관한 수많은 개선이 반영되어있습니다.

MonoDevelop 2.0의 변경 사항은 아래와 같습니다.

  • MSBuild의 프로젝트 파일을 잘 지원하도록 만들어졌습니다.
  • 프로젝트/솔루션 당 정책 기능이 구현되어있습니다.
  • Vala 프로그래밍 언어를 지원합니다.
  • 솔루션 탐색기에서 다중 선택이 가능하게 되었습니다.
  • 패드/문서 선택 기능이 제공됩니다.
  • 문맥어 검색을 지원하는 파일로 이동 기능이 제공됩니다.
  • 새로 개선된 어셈블리 브라우저가 제공됩니다.
  • 웹 개발 시 코드 자동 완성 기능이 향상되었습니다.
  • 태그의 깊이를 나타내는 Path Bar와 문서 아웃라이닝 기능이 추가되었습니다.
  • 자동 완성 기능 및 C# 3.0에 관한 코드 에디터 지원이 강화되었습니다.
  • 코드 접이, 분할 보기, 컬러 스키마, 증분 검색을 지원하는 새로운 코드 에디터가 도입되었습니다.
  • VI 모드가 지원됩니다.
  • 문서 아웃라인 패드 기능이 추가되었습니다.
  • XML 편집이 좀 더 편리하고 쉬워졌습니다.
  • 디버거에서 MDB (Mono 디버거 파일), GDB (네이티브 디버거 파일)을 지원합니다.
  • 버전 관리 기능, GTK# 디자이너 등 기존 기능에 대한 개선도 많이 이루어졌습니다.

좀 더 자세한 내용은 Mono 2.4 릴리즈 노트 (http://www.mono-project.com/Release_Notes_Mono_2.4)와 MonoDevelop 2.0 릴리즈 노트 (http://www.monodevelop.com/Download/MonoDevelop_2.0_Released)를 참고하십시오.

크리에이티브 커먼즈 라이선스
Creative Commons License

'Software Development > Mono' 카테고리의 다른 글

C#, .NET으로 Apple iPhone 프로그램 만들기  (2) 2009/08/04
Mono Tools for Visual Studio 소개  (2) 2009/07/01
Mono 2.4 / MonoDevelop 2.0 런칭  (0) 2009/04/01
Moonlight 1.0이 공개되었습니다.!  (0) 2009/03/03
Mono 2.2 출시  (0) 2009/01/16
Mono 2.0 릴리즈 노트  (4) 2008/11/03
Posted by Windows Azure MVP 남정현 (rkttu.com)