'Language'에 해당되는 글 14건

  1. 2008/04/16 귀차니스트 std::ostreambuf_iterator, std::istreambuf_iterator의 이유 (1)
  2. 2008/04/13 귀차니스트 std::auto_ptr - Smart Pointer 이지만?? (1)
  3. 2008/04/10 귀차니스트 RCW 에러의 원인 - ??? (2)
  4. 2008/04/07 귀차니스트 C# Application - Main 에서 Try-Catch 오작동 해결하는 방법 (7)
  5. 2008/03/21 귀차니스트 C# Generics - Generics 문법의 사용법

  저도 STL에 있어서 많은 것을 알고 있는 사람이 아니고, 아직 미숙하지만 개중에 입출력과 관련해서 유용한 iterator가 있다는 것을 알아 유용하게 사용하고 있습니다. 제가 사용하는 부분은 std::copy 알고리즘에서 std::ostream_iterator를 이용한 개체 내용의 출력부분입니다. 이를 이용한 코드는 저번에도 포스팅이 되었던 내용입니다. 그런데 이 ostream_iterator, istream_iterator에 대하여 Effective STL에서 한 가지 주제가 존재하여서 그에 대한 내용을 보려고 합니다.

iteratorbuf_iterator.cpp (Language : cpp)
  1. #include <iostream>
  2. #include <algorithm>
  3. int main( int argc, char **argv )
  4. {
  5.     std::copy( ( std::istreambuf_iterator< char >( std::cin ) ), std::istreambuf_iterator< char >(), std::ostreambuf_iterator< char >( std::cout ) );
  6.     return 0;
  7. }

  주로 사용은 이렇게 하더군요. 이게 가능한 까닭은 바로 다음과 같은 코드에 있다는 것이 중요합니다.

copy.cpp (Language : cpp)
  1. template<class _InIt, class _OutIt>
  2. inline
  3. _SCL_INSECURE_DEPRECATE
  4. _IF_NOT_CHK(_OutIt) __CLRCALL_OR_CDECL copy(_InIt _First, _InIt _Last, _OutIt _Dest)
  5. {   // copy [_First, _Last) to [_Dest, ...)
  6.     return (_Copy_opt(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Dest,
  7.         _Iter_random(_First, _Dest), _Ptr_cat(_First, _Dest), _Range_checked_iterator_tag()));
  8. }
istreambuf_iterator.cpp (Language : cpp)
  1. template<class _Elem,
  2.     class _Traits>
  3.     class istreambuf_iterator
  4.         : public iterator<input_iterator_tag,
  5.             _Elem, typename _Traits::off_type, _Elem *, _Elem&>
  6. .
  7. .
  8. .
  9. _Elem operator*() const
  10. {   // return designated value
  11.     if (!_Got)
  12.         ((_Myt *)this)->_Peek();
  13.  #if _HAS_ITERATOR_DEBUGGING
  14.     if (_Strbuf == 0)
  15.         _DEBUG_ERROR("istreambuf_iterator is not dereferencable");
  16.  #endif /* _HAS_ITERATOR_DEBUGGING */
  17.     return (_Val);
  18. }
ostreambuf_iterator.cpp (Language : cpp)
  1. template<class _Elem,
  2.     class _Traits>
  3.     class ostreambuf_iterator
  4.         : public _Outit
  5. .
  6. .
  7. .
  8. _Myt& operator=(_Elem _Right)
  9. {   // store element and increment
  10.     if (_Strbuf == 0
  11.         || traits_type::eq_int_type(_Traits::eof(),
  12.         _Strbuf->sputc(_Right)))
  13.     _Failed = true;
  14.     return (*this);
  15. }

  Copy 알고리즘에서는 iterator이기 때문에 *연산자를 통하여 값을 읽어오게 되고, ostreambuf_iterator에 = 대입 연산자로 값을 입력하기 때문에 그렇습니다. 실제로 대충 돌아가는 루틴이 눈에 보이시죠?^^. 이 istreambuf_iterator, ostreambuf_iterator와 istream_iterator, ostream_iterator가 다른 점은 기타 점도 있겠지만 출력에 있어서 값을 읽어오고 값을 출력하는 부분이 _Strbuf 를 이용한 직접 액세스 라는 점입니다.

istream_iterator.cpp (Language : cpp)
  1. template<class _Ty,
  2.     class _Elem = char,
  3.     class _Traits = char_traits<_Elem>,
  4.     class _Diff = ptrdiff_t>
  5.     class istream_iterator
  6.         : public iterator<input_iterator_tag, _Ty, _Diff,
  7.             const _Ty *, const _Ty&>
  8. .
  9. .
  10. .
  11. const _Ty& operator*() const
  12. {   // return designated value
  13.  #if _HAS_ITERATOR_DEBUGGING
  14.     if (_Myistr == 0)
  15.     {
  16.         _DEBUG_ERROR("istream_iterator is not dereferencable");
  17.         _SCL_SECURE_OUT_OF_RANGE;
  18.     }
  19.  #else
  20.     _SCL_SECURE_VALIDATE_RANGE(_Myistr != 0);
  21.  #endif /* _HAS_ITERATOR_DEBUGGING */
  22.     return (_Myval);
  23. }
ostream_iterator.cpp (Language : cpp)
  1. template<class _Ty,
  2.     class _Elem = char,
  3.     class _Traits = char_traits<_Elem> >
  4.     class ostream_iterator
  5.         : public _Outit
  6. .
  7. .
  8. .
  9. ostream_iterator<_Ty, _Elem, _Traits>& operator=(const _Ty& _Val)
  10. {   // insert value into output stream, followed by delimiter
  11.     *_Myostr << _Val;
  12.     if (_Mydelim != 0)
  13.         *_Myostr << _Mydelim;
  14.  #if _HAS_ITERATOR_DEBUGGING
  15.     if (!*_Myostr)
  16.     {
  17.         _DEBUG_ERROR("ostream_iterator is not dereferencable");
  18.         _SCL_SECURE_OUT_OF_RANGE;
  19.     }
  20.  #else
  21.     _SCL_SECURE_VALIDATE_RANGE(*_Myostr != NULL);
  22.  #endif /* _HAS_ITERATOR_DEBUGGING */
  23.     return (*this);
  24. }

  buf_iterator와 다른 점은 <<, >> 연산자를 통하냐 통하지 않고 직접 액세스 하느냐에 따라 달렸습니다. 이 점 때문에 buf_iterator와 아닌 것의 속도 차이가 분명 존재하게 됩니다. 그래서 별 다른 문제가 존재하지 않고 buf_iterator로써 가능하다면 이 것을 사용하는 것이 속도상으로 좋다는 말이 여기서 나오는 말 일테구요.
  하지만 장점이 있다면 단점도 존재하겠죠??

Error.cpp (Language : cpp)
  1. #include <iostream>
  2. #include <algorithm>
  3. int main( int argc, char **argv )
  4. {
  5.     std::copy( ( std::istreambuf_iterator< char >( std::cin ) ), std::istreambuf_iterator< char >(), std::ostreambuf_iterator< int >( std::cout ) );
  6.     return 0;
  7. }

  이 코드를 실행해 보면 에러가 발생합니다. 그 이유는 바로 rdbuf 개체를 통한 직접 액세스를 std::cout 에서 하기 때문에 그렇습니다. 대충 이러한 오류가 발생하는 까닭은 std::cout이 다음과 같이 정의 되어있기 때문인것 같습니다.

cout.cpp (Language : cpp)
  1. __PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 ostream cout;
ostream.cpp (Language : cpp)
  1. typedef basic_ostream<char, char_traits<char> > ostream;

  위와 같이 정의가 되어있는데 basic_ostream이 int 형으로 됨으로 인하여 생성되는 Class 는  typedef basic_ostream<_Elem, _Traits> ostream_type; 와 같은 형태인데. 이 형태를 int 형 buf_iterator 내부에 존재하는 클래스와 호환이 안되기 때문에 그런 것 같군요.
  정확한 이유는 한 번 제대로 따라가봐야 할 것 같은데, 일단 결론만 얘기하자면 ostream_iterator는 int 형태로 잡아주어도 출력이 가능합니다. 위에 언급한 바와 같이 <<, >> 연산자로써 std::cout << 1; 을 실행하는 것과 동일하게 처리가 된다고 보시면 되니까요.

  buf_iterator 와 아닌 것의 차이를 대충 보았는데, 간단한 몇 자의 타자의 차이임에도 불구하고 속도의 차이가 벌어질 수 있다는 점. 놓칠 수 없다고 생각되지 않나요?^^. 하나하나 살펴보다 보면 모든 부분을 정복할 수 있을 것이라 생각이 드는군요^^;

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/04/16 22:33 2008/04/16 22:33

댓글을 달아 주세요

  1. 최익필 2008/07/27 21:16  댓글주소  수정/삭제  댓글쓰기

    트랙백이 가지 않아 댓글로 남겨 둡니다.^^ 입출력 스트림 라이브러리 찾덧 중에 좋은 정보가 있어서 들렸습니다.

    관련글 : http://ikpil.com/552

std::auto_ptr - Smart Pointer 이지만??

Language/C++ 2008/04/13 23:59 귀차니스트

  boost::shared_ptr 에 대해서는 이미 아시고 계실테고, 관심이 더욱 있으신 분, 혹은 이미 아시는 분들은 boost::scoped_ptr 에 대해서도 알고 계실겁니다. 그런데 C++ 에도 표준으로 원래 존재하는 Smart Pointer가 존재합니다. 그 이름은 auto_ptr<> 입니다. 어떤 것이냐구요??

autoptr.cpp (Language : cpp)
  1. #include <memory>
  2. #include <iostream>
  3. int main(int argc, char **argv)
  4. {
  5.     std::auto_ptr< int > aa( new int );
  6.     *aa = 100;
  7.     std::cout << *aa << std::endl;
  8.     return 0;
  9. }

  대충 이렇게 사용합니다. 그럼 scope를 벗어 날때 auto_ptr의 ~소멸자가 호출됨으로 인하여 해당 보관 메모리를 해제하게 됩니다. 그런데 사용은 아주 간단하게 보이지만 신경 써주어야하는 점이 몇가지 있습니다. 무엇인가 하면 new와 new [], delete, delete []의 차이점 때문이죠.

~auto_ptr.cpp (Language : cpp)
  1. ~auto_ptr()
  2. {   // destroy the object
  3.     if (_Myptr != 0)
  4.         delete _Myptr;
  5. }

  소멸자에서 사용하는 부분이 delete [] 가 아닌 delete이기 때문에 실질적으로 생성자에서 new int 가 아닌 new int[ 100 ] 과 같은 구문을 사용하였을때, 하나의 개체를 제외하고는 소멸자가 호출되지 않습니다. 그리고 할당된 개체가 int, double 등의 기본 타입이 아닌 메모리를 또 개별적으로 관리하는 개체일 경우는 더 큰 문제가 발생하게 되겠죠.
  또 하나 생길 수 있는 문제점이란 무엇일까요?? 바로 = operator overloading으로 인한 소유권 이전에 대한 문제점입니다.

auto_ptr.cpp (Language : cpp)
  1. auto_ptr<_Ty>& operator=(auto_ptr<_Ty>& _Right) _THROW0()
  2. {   // assign compatible _Right (assume pointer)
  3.     reset(_Right.release());
  4.     return (*this);
  5. }
  6. void reset(_Ty* _Ptr = 0)
  7. {   // destroy designated object and store new pointer
  8.     if (_Ptr != _Myptr && _Myptr != 0)
  9.         delete _Myptr;
  10.     _Myptr = _Ptr;
  11. }

  이렇게 구현이 되어있기 때문에 _Right에 해당하는 개체는 _Myptr이 삭제 되고, 해당 개체가 소유권을 이전 받기 때문에 문제점이 존재할 여지가 있습니다.
  어떤 부분에서냐고 물어보신다면 물론 이 것이 STL Container 과 같은 부분에서 사용이 되거나, 코드 도중 사용이 된다면 소유권이 넘어감으로 인하여 예상치 못한 점이 발생할 수 있다는 점이죠. 물론 코딩을 하는 사람치고 이런 것을 알아보지 않고 바로 사용하는 경우는 거의 없겠지만, 보통의 경우를 생각하고 코딩할 경우는 무척 문제가 될 수 있습니다. 실제로 STL Container의 경우 내부에서 대입문이 존재하는 알고리즘을 사용했을 때, 개체에 대한 메모리가 존재하지 않는 경우가 생깁니다. 이는 프로그램이 예상대로 동작하지 않는다는 소리가 됩니다. 그로인해 프로그램은 오작동 혹은 버그가 생길테구요.
  이러한 점을 보았을 때엔, 편리하지만 문제점이 존재하는 소스 양날의 검이 되지 않기 위해선 사용하기 이 전에 파악을 먼저하고 사용해야 하지 않을까 하는 생각이듭니다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/04/13 23:59 2008/04/13 23:59

댓글을 달아 주세요

  1. kevin 2008/10/15 17:02  댓글주소  수정/삭제  댓글쓰기

    잘보고 갑니다.^^

    깔끔하게 정리하셨네요~

RCW 에러의 원인 - ???

Language/C# 2008/04/10 11:59 귀차니스트

  오늘 회사에서 옆에서 저와 같이 일하는 형이 C#에서 프로젝트를 하는데 있어서 문제가 생기더군요. 그 원인은 바로 COM 개체를 C# UserControl 로 Wrapping 한 뒤, 그 프로젝트에서 UserControl을 등록하여 폼에 위지윅 배치를 할 경우 "RCW개체에서 분리된 COM개체는 사용할 수 없습니다" 와 비슷한 에러가 뜨는 것이었습니다.
  그래서 집에 와서 대충 한 번 살펴보긴 했는데. 테스트 대상은 Windows Media Player 이었죠. 이것은 문제가 없더군요. 그래서 제가 임의로 추측하기론 멀티쓰레드를 고려하지 않은 즉, Thread-Safe하지 않은 Com 개체에 있어서는 에러가 생긴다고 판단하였습니다.
  실제로 Com 개체의 코드를 보면 대충 이렇게 구현이 되어있죠.

ComExample.cpp (Language : cpp)
  1. #pragma once
  2. #include "resource.h"       // 주 기호입니다.
  3. #include <boost/function.hpp>
  4. #include <string>
  5. #include <stack>
  6. #include <cmath>
  7. #include <map>
  8. #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
  9. #error "단일 스레드 COM 개체는 전체 DCOM 지원을 포함하지 않는 Windows Mobile 플랫폼과 같은 Windows CE 플랫폼에서 제대로 지원되지 않습니다. ATL이 단일 스레드 COM 개체의 생성을 지원하고 단일 스레드 COM 개체 구현을 사용할 수 있도록 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA를 정의하십시오. rgs 파일의 스레딩 모델은 DCOM Windows CE가 아닌 플랫폼에서 지원되는 유일한 스레딩 모델이므로 'Free'로 설정되어 있습니다."
  10. #endif
  11. // CCCalculator
  12. class ATL_NO_VTABLE CCCalculator :
  13.     public CComObjectRootEx<CComSingleThreadModel>,
  14.     public CComCoClass<CCCalculator, &CLSID_CCalculator>,
  15.     public IDispatchImpl<ICCalculator, &IID_ICCalculator, &LIBID_IPangYaLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
  16. {
  17. public:
  18.     CCCalculator()
  19.     {
  20.     }
  21. DECLARE_REGISTRY_RESOURCEID(IDR_CCALCULATOR)
  22. BEGIN_COM_MAP(CCCalculator)
  23.     COM_INTERFACE_ENTRY(ICCalculator)
  24.     COM_INTERFACE_ENTRY(IDispatch)
  25. END_COM_MAP()
  26.     DECLARE_PROTECT_FINAL_CONSTRUCT()
  27.     HRESULT FinalConstruct()
  28.     {
  29.         return S_OK;
  30.     }
  31.     void FinalRelease()
  32.     {
  33.     }
  34. };
  35. OBJECT_ENTRY_AUTO(__uuidof(CCalculator), CCCalculator)

  위에서 보는 코드와 비슷한 Com Object Class 들에서 static 코드가 존재하는 Com 개체였기에 해당 에러가 발생하지 않았나 생각합니다.
  그런데 신기한건 VS.net 2003 에서는 또 별다른 문제가 없이 작동하는 Wrapping 방법이었다는 점이죠. 이 역시 아마 VS.net 2005 로 넘어가면서 IDE 자체의 큰 변화가 있었고, 작동방법이 다르게 구현이 되었기 때문이지 않을까 생각합니다.
  막연한 추측이긴 합니다만 공통된 주제를 가지고 다음에도 토론이 되었으면 하고 포스팅을 합니다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/04/10 11:59 2008/04/10 11:59
TAG , ,

댓글을 달아 주세요

  1. kkamagui 2008/04/21 09:27  댓글주소  수정/삭제  댓글쓰기

    쿠아~ 그런 문제도 있구나~
    완전 어렵네... ㅜ_ㅜ... 천지 이래가되긋나 ㅜ_ㅜ

  오늘 정말 희한한 현상을 겪게 되었습니다. 그게 뭐냐하면 바로 C#의 Main단에서 Try-Catch 구문을 걸었는데 제대로 Catch가 걸리지 않았던 것이죠. 그 때는 참 황당했습니다. 왜냐구요? Visual Studio.Net을 C++개발자 타입으로 설정하였을 때, 디버그 모드로 프로세스를 실행하면 Catch까지 잘 걸리는데, 단독 프로세스로 실행했을 경우엔 Catch에 제대로 걸리지 않더군요. Application.Run 내부적으로 처리하는 것 같았습니다.

Program.cs (Language : csharp)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Windows.Forms;
  5. namespace WindowsFormsApplication3
  6. {
  7.     static class Program
  8.     {
  9.         /// <summary>
  10.         /// The main entry point for the application.
  11.         /// </summary>
  12.         [STAThread]
  13.         static void Main()
  14.         {
  15.             try
  16.             {
  17.                 Application.EnableVisualStyles();
  18.                 Application.SetCompatibleTextRenderingDefault(false);
  19.                 Application.Run(new Form1());
  20.             }
  21.             catch
  22.             {
  23.                 MessageBox.Show("테스트 Catch");
  24.             }
  25.         }
  26.     }
  27. }

Form1.cs (Language : csharp)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. namespace WindowsFormsApplication3
  10. {
  11.     public partial class Form1 : Form
  12.     {
  13.         public Form1()
  14.         {
  15.             InitializeComponent();
  16.         }
  17.         private void button1_Click(object sender, EventArgs e)
  18.         {
  19.             string aa = null;
  20.             aa.Substring(0);
  21.         }
  22.     }
  23. }

  코드는 대충 위와 같았습니다. Program.cs 에서 Application.Run으로 폼을 표시하고 내부적으로 메시지 펌핑(?)을 하게 될거라 생각을 한 후, Form1에서는 고의적으로 익셉션을 발생시키게 하였습니다. 여기서 바로 문제가 발생합니다. 어떤 거냐구요? Debug 모드로 실행을 한 번 해보시고, 단독 모드로 실행을 한 번 해보십시오. 단독으로 실행을 하면 C#의 기본 Exception MessageBox(?)가 뜰거에요. 절대 메시지 박스가 뜨지 않습니다.
  그래서 결국 구글링을 하다가 찾게 된 페이지에서 하나의 해결책을 발견하고 적용시켜보니 제대로 작동이 되었습니다.


  찾은 코드를 한 번 적용 시켜 보겠습니다. 그럼 Program.cs에 존재하는 코드에 한 줄이 추가됩니다.

Program.cs (Language : csharp)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Windows.Forms;
  5. namespace WindowsFormsApplication3
  6. {
  7.     static class Program
  8.     {
  9.         /// <summary>
  10.         /// The main entry point for the application.
  11.         /// </summary>
  12.         [STAThread]
  13.         static void Main()
  14.         {
  15.             try
  16.             {
  17.                 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
  18.                 Application.EnableVisualStyles();
  19.                 Application.SetCompatibleTextRenderingDefault(false);
  20.                 Application.Run(new Form1());
  21.             }
  22.             catch
  23.             {
  24.                 MessageBox.Show("테스트 Catch");
  25.             }
  26.         }
  27.     }
  28. }

  Application.SetUnhandledExceptionMode를 ThrowException으로 설정하도록 하니 단독 모드에서도 테스트 Catch 메시지 박스 코드가 존재하는 Catch가 걸립니다. 아마도 추측하기론 Run 내부에서 Try-Catch를 설정하는 듯도 보이는 군요. 30분 정도 이 것때문에 삽질을 하긴 했지만 다음에 이런 일이 발생했을 때는 아주 유용할 것이라 생각합니다.^^

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/04/07 20:49 2008/04/07 20:49

댓글을 달아 주세요

  1. kkamagui 2008/04/09 10:24  댓글주소  수정/삭제  댓글쓰기

    오~ 꽤나 괜찮은 정보네~ ;)

    블로그의 질이 갈수록 높아지는구나 @0@)/~ 홧팅이다~

  2. 준호씨 2008/04/09 16:22  댓글주소  수정/삭제  댓글쓰기

    뭐냐뇽 ㅡ_ㅡ;
    오작동 미워요;

  3. 준호씨 2009/11/23 14:53  댓글주소  수정/삭제  댓글쓰기

    C# 예외처리 찾다가 다시 오게 되는구만 ㅋ
    그나전 C# 쓰면 쓸수록 뭔가 이상하노 -_-; 내가 아직 적응을 못한건감...

    • 귀차니스트 2009/11/25 04:59  댓글주소  수정/삭제

      무엇이 말이삼??
      java 에서 checked-exception 인가??
      throw 로 지정하는거 그건 안되지 싶어 ㅋㅋ

      전체는 그냥 Exception 으로 받아서 하면 될거고..
      Exception을 Inherit 받아서 override 해줌 너만의 Exception 이 되지 않을까..

  4. 준호씨 2009/11/26 00:32  댓글주소  수정/삭제  댓글쓰기

    Java한참 쓰면서.. C#이 Java랑 비슷할거라 생각을 했었는데 여엉 이상하넹 -_-;
    예를 들어
    lblBankName.Text = (String)dr["bankname"];
    이런식으로.. Getter, Setter 도 잘 사용안하고 ToString() 이런거 안쓰고 (String)으로 type을 바꾼다거나 ["bankname"] 처럼 이상한 형식으로 배열을 사용한다거나 -_-; 암튼 구질구질 허구만...
    자바였다면
    lblBankName.SetText(dr.getString("bankname";)); 이런식으로 코딩 했겠지
    예외는 아직 많이 안써봐서 좀 더 써보고 평가 해 볼 수 있을듯 함.

C# Generics - Generics 문법의 사용법

Language/C# 2008/03/21 23:29 귀차니스트

  C++을 다루어보았고, 어느정도 고급쪽의 기술을 알게된다면 Template라는 것을 사용해보셨을 겁니다. 개념상 기존의 프로그래밍과 다른 패러다임을 띄고 있고 데이터표현의 완전성을 지니기 때문에 새로운 것이죠. 그럼 Generics 라는 것은 혹시 들어보셨는지 모르겠습니다. Generics는 Java나 .Net 환경에서 지원하는 새로운 문법입니다. Template보다는 제약이 심하고, 컴파일러 측면에서 지원해주는 그런 문법입니다. 역시 말만 해서는 알아듣기 힘들겠죠??

Generics.cs (Language : csharp)
  1. public class Xml<T>
  2. {
  3. }

  다음과 같이 사용한다면 해당 Xml클래스 내부에서는 T 형을 데이터 타입으로 취하는 개체를 생성하여 사용할 수 있습니다. 바로 Template와 동일하죠. 대신 많은 부분에서 C++ Template와 동일한 기능들을 제공하지는 않습니다. 그리고 template< typename T >와 같은 키워드를 사용하지 않고도 <T>만 붙여줘도 Generics기능이 작동하게 됩니다. 그런데 한 가지 추가적인 기능이 존재하죠. T에 대한 데이터 타입의 제한을 걸어버릴 수 있죠.

Where.cs (Language : csharp)
  1. public class A
  2. {
  3. }
  4. public class B
  5. {
  6. }
  7. public class Xml<T> : XmlLayer where T : A
  8. {
  9. }

  위와 같은 where T : A 라는 조건을 달아줄 경우 T의 데이터 타입은 A 혹은 A에서 파생된 개체로 제한이 걸리게 됩니다. 만약 다른 타입을 넣으려고 한다면 컴파일러 자체에서 지정할 수 없는 형태라고 에러가 발생하죠. 이 방법을 사용하면 데이터 타입을 제한하고자 할 때는 원하는 목적만큼 코딩을 수행할 수 있게 됩니다. 특히 라이브러리를 개발하는 쪽에서는 그 라이브러리를 사용하는 쪽이 한 가지의 방법 외 다른 방향으로 빠지지 않도록 도와주어야 하는데, 이러한 부분에서 도움을 주게 되는 것이죠. 약간은 부족할 지도, 편리할지도 모르는 문법이지만 어느 것이나 그렇듯이 잘 사용한다면 아주 강력한 무기가 될 수 있겠죠^^

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/03/21 23:29 2008/03/21 23:29
TAG , ,

댓글을 달아 주세요