2010년 6월 28일 월요일

C# short.Parse and short.TryParse Methods

원문 : C# short.Parse and short.TryParse Methods








C# short.Parse and short.TryParse Methods


 string 데이터를 short 데이터 타입으로 변환할 때 short.Parseshort.TryParse 를 사용하면된다. 두 메서드의 결과는 똑같지만 사용함에 있어 에러가 발생했을 때의 차이점을 알아두자.


Using short.Parse and short.TryParse

short.Parse 와 short.TryParse 사용 예제이다.

const string value1 = "100";
const string value2 = "100000";

short sh1 = short.Parse(value1);
Console.WriteLine("sh1 = {0}", sh1);

short sh2;
if (short.TryParse(value1, out sh2))
    Console.WriteLine("sh2 = {0}", sh2);

short sh3;
if (short.TryParse(value2, out sh3))
    Console.WriteLine("sh3 = {0}", sh3);



short 데이터 타입이 저장할 수 있는 값의 범위는 2Byte(+- 3만2천) 이다. short.Parse메소드를 이용하여 100 은 저장하는데 문제가 없다. 하지만 예제에는 없지만 short.Parse 메소드에 100000을 저장하려 했다면 예외가 발생할 것이다. short.TryParse 메서드는 인자로 전달한 값을 저장 가능한지를 리턴값으로 리턴한다. 100000을 저장하려 했다면 false 를 리턴한다.

short.Parse 는 데이터 변환 시 잘못된 변환에 있어서 예외를 리턴하고, short.TryParse 메소드는 잘못된 변환에 있어 false 를 리턴한다.

2010년 6월 8일 화요일

C# DayOfWeek Enum

원문 : C# DayOfWeek Enum






C# DayOfWeek Enum









  아마 한번쯤은 코딩할 때 요일 관련 코딩을 해봤을 것이다. Win32API 에서는 요일값이 1, 2, 3, ... 이런 식으로 정수값으로 얻을 수 있기 때문에 이 값을 다시 Enum 으로 정의해서 사용하곤 했는데 .NET 에서는 이 Enum 열거형 조차 만들어 주었다. 



DayOfWeek  열거형의 네임스페이스는 System 에 정의되어 있다.








바로 정수값을 사용해도 되지만 DayOfWeek 열거형을 사용해야 하는 이유는 다른 타입에서 DayOfWeek 타입을 지원하기 때문에

사용하기 편리하기 때문이 아닐까 생각해 본다.



아래는 예제 코드이다. DateTime 클래스와 같이 사용할 수 있기 때문에 편리하다.












2010년 6월 4일 금요일

C# Marshal : 데이터 변환





C# Marshal : 데이터 변환














 대부분에 있어 Managed 의 string 을 Unmanaged 의 CString 이나 LPSTR 로 변환하는 경우가 많았는데 오늘 다른 타입으로 변경해야 되는 경우가 생겼다... 시간좀 많이 소비한것 같다..











■ 윈도우 핸들(HWND) 변환





Win32API나 MFC를 보면 함수 파라미터로 윈도우 핸들 즉, HWND 를 많이 사용한다. Managed Code 에서 HWND에 대응하는 타입은 IntPtr 이다.


HWND ↔ IntPtr





IntPtr 은 void * 또는 핸들타입에 사용된다.





호출하고자 하는 함수 선언



void Func(HWND hWnd);




Managed Code delegate



[UnmanagedFunctionPointer(CallingConvention.Cdel)]
private delegate void deleFunc(IntPtr hWnd);




참고로 Control을 상속받는 클래스에서는 Handle 프로퍼티로 쉽게 핸들값을 얻을 수 있다. Handle 프로퍼티는 컨트롤 창의 핸들값을 IntPtr로 리턴한다.



[BrowsableAttribute(false)]public IntPtr Handle { get; }












■ out 타입 포인터 변수 전달





Unmanaged Code 의 함수가 인수로 DWORD * 타입을 갖으며 해당 포인터 변수에 값을 저장한다. 따라서 이 함수를 호출하고 난 뒤에 포인터 변수에 저장된 값을 조사해서 사용하는 경우이다.






호출하고자 하는 함수 선언



void Func(DWORD *pdwListenPort);






Func 함수 호출결과 pdwListenPort 포인터 변수에 값을 얻게 된다. 즉, out 속성.





Managed Code delegate



[UnmanagedFunctionPointer(CallingConvention.Cdel)]
private delegate void deleFunc(out IntPtr pdwListenPort);






마샬링에서 void * 는 IntPtr 로 매칭된다.


void * ↔ IntPtr





DWORD * 이므로 일단 IntPtr 을 사용하였고, 메소드 결과 포인터 변수로 값을 얻으므로 out 키워드를 사용하였다.


IntPtr 은 void * 이므로 DWORD * 형식의 데이터를 얻기 위해선 적절한 타입 캐스팅을 해주면 된다.


IntPtr 변수의 메소드로 To- 관련 메소드를 사용하면 쉽게 변환이 가능하다. 원래는 DWORD 는 32bit Unsigned int 타입이다. 그렇다면 Managed Code쪽에서는 uint 또는 UInt32 타입으로 변환해 주어야 한다. 올바르지 않지만 ToInt32() 메소드를 이용하여 변환해 주었다.


DWORD * (out 속성의 포인터 변수) ↔ out IntPtr






// deleFunc Func 에 연결

IntPtr value = IntPtr.Zero;
Func(out value);

Int32 tmp = 0;
tmp = value.ToInt32();










■ in 타입 포인터 변수 변환





C++ 에서 포인터 변수는 기본적으로 값을 읽고 쓸 수 있다. 물론 const 키워드를 통해 읽기만 가능하게 할 수는 있다. 이렇게 Managed Code 쪽에서 포인터 변수값을 읽고 쓸 수 있게 넘기는 법은 아직 구현해보지 못했다...


포인터 변수를 전달하여 값을 전달 받는 것은 위에 방법을 사용하면 되고 (■ out 타입 포인터 변수 전달),


포인터 변수의 값을 저장하여 전달하는 방법을 알아보자.





호출하고자 하는 함수 선언



void Func(DWORD *dwPort);




Managed Code delegate



[UnmanagedFunctionPointer(CallingConvention.Cdel)]
private delegate void deleFunc([MarshalAs(UnmanagedType.AsAny)] Object pdwPort);




우선 이 변환은 IntPtr 타입을 사용하지 않았다. MarshalAs 프로퍼티를 사용하였으며, AsAny 를 사용하였다.


여기서 AsAny 설명은 다음과 같다.


런타임에서 개체의 형식을 결정하고 해당 형식으로 개체를 마샬링하는 동적 형식입니다. 플랫폼 호출 메서드에만 유효합니다.





사용 예



uint port = 9100;

Func(port);




즉, uint 값이 런타임시에 적잘하게 포인터를 만들고 port 값을 그 포인터 변수에 저장하여 Unmananged 코드에 전달하게 된다.







■ in/out 타입 포인터 변수 변환

왠만한 경우 위의 in 또는 out 타입 포인터 변수 변환으로 사용할 수 있는데 in, out 타입의 포인터 변수를 사용해야 할 때 어떻게 해야 할까? 아.. 근데 이 마샬링 변환을 매번 사용하는게 아니라 간혹가다 사용하니 할때마다 새롭다...

호출하고자 하는 함수 선언


void Func(DWORD *dwPort);



dwPort 포인터 변수에 값을 설정하여 Func함수에 전달한다. Func함수 호출 후 dwPort에 새로운 값이 저장된다.

Managed Code delegate

[UnmanagedFunctionPointer(CallingConvention.Cdel)]
private delegate void deleFunc(ref uint pdwPort);





DWORD 는 Unsigned int 32bit 타입이브로 C#의 uint 별칭을 사용한다.


uint portNum = 0;
Func(ref portNum); 


Func함수 호출 후 새로운 값이 portNum에 저장되어 있다.



■ LPCTSTR

LPCTSTR ↔ [MarshalAs(UnmanagedType.LPWStr] string







참조)








@