'Functional World/C#' 카테고리의 글 목록 :: iopeni - Think of C#



뜬금이 없다.. 랄까? 갑자기 웬 API??랄까? 이젠 쓸 일도 없는 녀석을 왜??? 랄까? 암튼 좀 그렇다.

작금의 상황은 이런 SendMessage보다... 더 좋은 모델들이 많이 있다. 굳이 SendMessage를 쓰는 것은... ㅜ,.ㅜ;; 좀 절망 이라고 할까.... 물론 가볍고 빠르다는 장점으로 인해 이 SendMessage를 사용하는 분들도 많이 있다.


어찌되었든.. 이 SendMessage라는 녀석을 이해 하려고 하면 기본 지식 부터 정리 하는 것이 좋을 듯 하다. 


옛날 DOS 시절을 생각 하면 그 땐 너무 행복한 시절이었다. 이런 SendMessage같은 녀석들이 없었으니 말이다. 하긴 그땐 인터럽트 때문에 어려웠다.


우리가 사용하고 있는 윈도우은 멀티 태스킹 환경이라는 것은 뭐 설명하지 않아도 다들 알고 있는 내용일 것이다. 모르는 사람들을 위한 팁으로 멀티 태스킹 환경이라는 것은 동시에 여러개의 프로그램을 실행 할 수 있는 환경 이라는 소리다. 


여러개의 프로그램이 동시에 실행 된다면 각각의 프로그램은 메모리 영역을 할당 받게 되는데 이는 보호되고 있어서 해당 프로그램 이외에 다른 프로그램은 메모리 영역에 접근 할 수 없다. (옛날 윈도우 3.1 또는 윈도우 95 시절에 윈도우가 무수히 블루 스크린을 띄웠는데 이게 이 메모리 영역의 침범으로 인한 오류로 컴퓨터를 재부팅 해야 하는 시절도 있었다. 지금은 거의 없어진 증상이지만...)


이렇게 여러개의 프로그램이 실행되어 있는 상황에서 각각의 프로그램들이 특정 데이타를 공유 할 필요성이 대두 되었고 여러개의 프로그램이 데이타를 공유 할 수 있는 방법을 통칭 IPC(Inter-process Communication)라고 한다.


그러하기에 IPC라는 것은 여러가지 방법을 가지게 될 것이다. 프로세서간 정보만 공유 하면 되는 것이기에 소켓 또는 파일 또는 레지스트리등을 사용할 수도 있을 것이다. 정말 많은 방법이 있을 것이므로 우리는 이 많은 방법들 중에 어떤 방법을 선택 해야 하며, 이때 고려 해야 할 요소들이 있는데 대충 다음과 같다.


1. Network을 고려 해야 하는가?

   1-1 통신 하려고 하는 대상의 OS가 같은가?

   1-2 통신 하려고 하는 대상의 OS종류는 한가지 인가?

2. 통신의 속도가 중요하게 고려 되어야 하는가?

3. 반복적 정보 공유 인가?

4. 통신하고자 하는 정보의 사이즈는 큰가? 작은가?


여러가지 고려 요소를 생각 하여 방법이 정해 지면 추 후 방법을 바꾸고자 할 경우 무척 어려운 상황이 발생 되므로 처음 선정 할때 부터 주의를 요해야 한다.


그럼 우리가 사용하는 Windows 환경에서의 메시지 전송 방법엔 어떤 방법들이 있는지 보자. 


1. 메지시 : 사용자 정의 메시지로 정보 전달 한다.

2. 클립보드 : 중앙 저장소를 이용한 대량의 정보 교환

3. DDE : Do Data Exchange를 이용한 지속적 정보 교환

4. 파일 맵핑 : 파일 맵핑을 이용한 메모리 공유

5. 메일 슬롯 : 메일 슬롯 사용

6. 파이프 : 파이프 사용

7. 윈속 : 소켓 사용

8. RPC, RMI : Remote Procedure Call, Remote Method Innovation 을 이용한 방법

9. COM, DCOM, COM+, WebService, WCF 등을 이용한 방법.


뭐 이 포스트에서 이야기 되지 않은 다른 방법들도 많을 것이다. 사실 IPC라는 것이 데이타를 공유만 하면 되는 것이기에 그 목적에만 맞으면 IPC라고 할 수 있을 것이다.


오늘의 포스팅 목적은 사실 위 많은 IPC 중에 메시지에 해당하는 내용을 살펴 볼 것이다.


메시지는 사실 정보를 교환 할 수 있는 방법중에 가장 간단하고 가장 가볍고 가장 빠른 방법이다. 이 메시지를 이용하기 위하여 우리는 OS에 대한 어느 정도 기초적 지식을 습득해야 한다. 


가장 처음 이해 해야 되는 내용은 Message Queue 이다.


일단 힘들게 그림 그린 메시지의 흐름도 부터 확인 하자.




메시지 큐는 여러분이 키보드를 이용하여 입력 하거나 마우스를 가지고 아이콘을 클릭 하거나 하는 일련의 동작들이 담기게 되는 일종의 자료 구조 이다. 이 메시지 큐는 무한 루프를 돌면서 사용자의 입력을 기다리게 된다.


메시지루프의 형태는 다음과 같다.



GetMessage 함수는 메시지 큐로 부터 메시지를 가지고 온다. DispatchMessage는 WndProc 함수가 메시지 구조체에 들어 있는 윈도우 핸들을 이용할 수 있도록 메시지 데이터를 WndProc함수로 보낸다. 결국 우리는 메시지를 가로채기 위해 WndProc함수를 Override 하여 재정의 사용한다. 


TranslateMessage()는 DispatchMessage 전 키보드 또는 입력 메시지를 전 처리 할 수 있다. 이 함수는 PreProcessMessage로 보낸다. PreProcessMessage를 Override 하여 재정의 사용한다. 매개 변수에는  WM_KEYDOWM, WM_SYSKEYDOWN, WM_CHAR 및 WM_SYSCHAR 값을 사용할 수 있다. 


다음 그림을 통해 메시지 루프를 조금 더 자세히 들여다 보자. 


이 그림에서 주의 깊게 보아야 할 항목은 PostMessage는 시스템 메시지 큐에 담긴다는 것이다. 이 때문에 SendMessage와 PostMessage가 몇가지 다른 특성을 보이게 된다. 


첫번째 차이점은 PortMessage는 비 동기 이다. (메시지 큐로부터의 응답을 기다리지 않는다.) SendMessage는 동기 이다. (메시지 큐로부터의 응답을 기다린다.)


이쯤 공부 했으니.. 이제 샘플을 보자. 


위의 샘플은 WM_COPYDATA 메시지를 이용하였다 이것은 메시지 전송을 할 경우 간단한 문자 메시지를 교환 하더라도 아주 복잡한 방법이 동원 되어야 하기 때문에... (이 예제는 다음 사이트에서 볼 수 있다. http://www.pinvoke.net/default.aspx/user32/SendMessage.html ) 윈도우에 추가된 메시지 이다.


두번째 차이점이 여기에 있다. PostMessage는 시스템 메시지큐에 들어가기 때문에 이 WM_COPYDATA 메시지를 사용할 수 없다.


추가적인 사항으로 SendMessage를 이용한 Broad-Casting 이다. 말 그대로 브로드 캐스팅이면... 여러개의 프로그램에 동시에 메시지를 날릴 때 이용 하는 방법 이란 것을 알 수 있을 것이다. 



위 예제 에서 주의 깊게 보아야 할 항목은 RegisterWindowMessage 이다. MSDN - https://msdn.microsoft.com/ko-kr/library/vstudio/ms644947(v=vs.110).aspx에서 확인 할 수 있다.


참고로 약간의 설명을 하자면 다음과 같다. RegisterWindowMessage는 응용 프로그램에서 정의한 메시지를 등록하고 그 메시지가 중복되지 않도록 해서 이미 등록된 다른 메시지와 충돌이 일어나지 않도록 한다. 


두 가지 별개의 프로그램에서 메시지를 주고 받으면서 의사 교환을 할 때 일반적인 (WM_USER, WM_USER + 1 등) 메시지 번호를 사용하는 것은 안전하지 않다. 


갑자기 정리 하게된 내용이 너무 많다... 아 배고파~~~~~ 


Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

double 형이 가지고 있는 자리수 제한의 문제로 인하여 동일 한 수를 동일 한 수로 비교 하지 못할 경우....에 사용 가능한 짧은 코드 샘플....

Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

아무 것도 아닌(?) 팁이라고 해야 할까요?


사실 아무 것도 아닌 아주 간단한 팁입니다. C# 1에는 아주 특수한 타입이 하나 있습니다.


System.Type 을 상속 받은 값 형식의 자료형들은 null을 대입 할 수 없습니다.


그런데 이게 좀 곤란한 상황이 발생 할 때가 있습니다. 정의 할 수 없는 상태의 값들이 바로 그렇습니다. 사람이 살아 있는데 사망일을 기록하여야 한다면 DB에는 아마도 null을 대입하게 될 것입니다.


이 null을 어플리케이션 레이어로 들고 나와서 DateTime 타입의 변수에 저장 하려고 하면 값 형식 이기 때문에 대입 할 수 없고 이 상황은 오류를 발생 시킵니다.


이 문제를 해결 하기 위하여 Nullable 이라는 아주 특수한 자료형이 있습니다. 


Nullable<DateTime> a = null; 


과 같이 DateTime 자료형에 null을 대입 할 수 있도록 하는 아주 특수한 자료형이죠!


이 자료형이 C# 2 로 오면서 좀 더 사용하기 쉬워졌습니다.


DateTime? a = null;


과 같이 말이죠 Type 에 ?을 적어 줌으로 인해서 null을 대입 할 수 있습니다.


오늘 이야기를 하려고 하는 것은 Nullable 자료형을 이야기 하려고 하는 것은 아닙니다.


널인 값을 널이 대입될 수 없는 값 형식 자료형에 대입 하려고 하면 오류가 리턴 될 것이고, 이 변수가 널인지 아닌지 우리는 if else 문 또는 bool ? true : false;의 3항 연산자를 사용하게 됩니다.


참 이런 문장을 쓸 때 마다 답답합니다. 특히나 DB에서 들고 나와야 하는 필드가 무지 많은 상황이고 쿼리에 NVL을 이용한 널 처리를 하지 않았다면 또는 DateTime에 아주 특수한 의미의 MagicValue 라고 불리우는 개발자 나름대로의 규칙 즉 지금은 사용하지 않을 어떤 값을 특수한 목적의 상태를 가리키는 값으로 활용 아직 죽지 않은 사람이라면 사망일에 1년 1월 1일 과 같은 값을 대입하고 어플리케이션에서 1년 1월 1일 인 사람은 살아 있다고 판단하게 하는 ....


뭐 이런 상황이라면 각 필드 별로 많은 조건 판단을 하게 됩니다. 


이런 상황에서 만약 널이 아니면 값을 그대로 대입하고 널이라면 다른 값을 대입하라 라는 삼항연산자의 조건을 조금 더 쉽게 정리 할 수 있는 식이 있다면 얼마나 좋을까요?


Microsoft는 기대를 저버리지 않았습니다.


바로 널 병합 연산자라고 불리우는 ?? 가 바로 그것 입니다.


아래 와 같은 문법이죠..


int? a = null;

int b = a ?? 5;


와 같이 쓰는 거죠. 이 녀석은 중첩 될 수 있습니다.


int b = null ?? null ?? null ?? ........ ?? 5;


처럼 말이죠.


이 널 병합 연산자는 저에게 매마른 대지에 단비 처럼.. 저의 복잡하고 읽기 힘든 코드를 깔끔하게 정리 하게 해준..... 정말 고마운 녀석입니다.

Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

객체 소거에 대한 단상....


얼마 전 아는 분이 몇가지 기술 적 자문을 구해 오셔서 그분 회사의 코드를 보던 중 질문 하신 범위 밖의 코드가 아주 심각한 문제가 있음을 발견 했습니다. 보고도 이야기 하지 않았습니다만..... 이야기 한다고 해서 그분이 이해 하시기엔 상당한 에로 사항이 있을꺼라는 ..... 제가 나쁜 놈이겠죠?


엔더스 헤일스버그라는 이 시대의 용자 께서는 .Net 을 설계 하시며, 절대 어플리케이션이 죽어서는 안된다 라는 명제를 가지고 정말 많은 고민을 하시었고(정말 고민을 했는지는 저도 모릅니다. 그냥 추측일 뿐입니다.)  생성된 객체가 소거 되었을 때, 누군가 소거된 객체를 호출 할 경우 어플리케이션의 종료를 막을 수 없고, 이 문제를 해결 하기 위하여, 가베지 컬렉터를 사용하여, 1세대, 2세대등...  사용자가 소거를 하여도 즉시 소거 되지 않고 가베지 컬렉터가 정말 사용하지 않는 객체를 소거 할 수 있도록 하는 시스템을 설계 하셨습니다.


아시는 분의 회사 코드를 보면 다음과 같은 황당한 코드가 담겨 있습니다.


private LIst<object> = new List<Object>();


public void funcion()

{

list.Clear();

list.ADD(new userControl);


//Todo....

}


그리고 화면에서 function을 호출 합니다.


결국 메소드가 한번 호출 될 때 마다 List를 비우고 다시 객체를 생성하여, 리스트에 담아 두게 되는데, 담겨 있는 객체를 소거 하는 문장은 어디에서도 찾아 볼 수 없습니다.결국 만든 유저 컨트롤 또 만들고, 또 만들고, 또 만들고........


엔더스 헤일스버그라는 이 시대의 용자가 설계한 마인드로 볼 때 결국 위와 같은 코드로 생성된  UserControl은 프로그램이 종료 될 때 까지 절대 소거 되지 않습니다. 


즉 Memory Leak 이 발생 한 거죠. 


만약 이 유저 컨트롤이 정말 큰 데이타를 취급 하게 된다면.... 이 프로그램이 메모리 부족 오류를 던지며, "나 일 못하겠다... 써글..." 이라고 이야기 하는 것은 시간 문제 입니다.


하나의 프로세스당 제한된 스레드 갯수... 하나의 스레드당 제한된 메모리 량을 생각 해 보면..... 사용 컴퓨터의 용량에 따라 어느 정도 가변적 이겠으나, 아주 위험한 코드죠 위와 같은 코드는.....


그래서 컬렉션에 있는 객체를 어떻게 소거 하여야 할까? 라는 문제를 생각해 보면 상당히 많은 방법들이 존재 합니다.


아주 무식한 방법으로 컬렉션에 담겨 있는 Controls를 Foreach로 순환 하며, 명시적 타입 캐스팅을 통한 타입 캐스팅 이후 각 타입이 가지고 있는 Dispose()를 호출 할 수도 있으나, 만약 저 List에 담기는 타입이 늘어 나면 늘어 날 수록 이 방법은 절대적 부담으로 작용 합니다. 


리스트에 담겨 있는 타입을 타입 캐스팅 해서 그 타입이 소거 대상 타입이라면 소거 하라는 메소드로 이관 하고 그 이관된 각 객체가 정말 이 시점에서 소거 하여야 하는 가를 검증 하는 잡이 발생 하게 되면... 이건 정말... 가관 입니다.


욕 나오는 코드를 작성 하게 되죠... 아마도 많은 초급 개발자 분들 께서는 이렇게 난해한 코드를 작성 하리라 생각 합니다.


그래서 살짝 힌트 아닌 힌트를 정리 합니다.


컬렉션에는 아주 유용한 메소드가 하나 있습니다.


ofType 메소드가 바로 그것이죠... 


이거에 확장 메소르를 하나 연결 하면 아주 쉬운 정리가 이루어 집니다. 다음 처럼 말이죠


//확장 메소드.

public static void ForEach<TItem>(this IEnumerable<TItem> sequence, Action<TItem> action)

        {

            // ToDo... 유효한 제거 인지에 해당하는 검증 작업 수행

                  검증하자....

// ---------------------------------------


            foreach(var item in sequence)

            {

                action(item);

            }

        }


// 컨트롤 클래스에서의 사용 이후 리스트 삭제 시점..

collection.OfType<IDisposable>().ForEach(ex => ex.Dispose());

collection.Clear();



짧은 코드로 원하는 잡을 수행 할 수 있다는 ..... ^^ 유용한 코드 입니다.





'Functional World > C#' 카테고리의 다른 글

라운드 트립 서식...  (0) 2015.05.06
널 병합 연산자.....  (0) 2014.12.15
윈도우 8.1 에서의 장치 독립적 코드 작성을 위한 DPI 설정 방법  (0) 2014.06.22
Form.ActiveForm  (0) 2013.11.07
바이트 배열 취득  (0) 2013.10.01
Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

Control 클래스는 Control의 위치와 크기를 지정하기 위해서 사용하는 Location 과 Size라는 두 개의 Property를 정의 하고 있습니다.


Location Property 는 Point Structure Type 으로 X 와 Y라는 두개의 int type field를 포함 합니다. 단위는 Pixel 입니다. Location Property 는 부모의 왼쪽 위 모서리로 부터 떨어진 상대적인 위치를 가리킵니다.


Size Property 는 width와 height라는 두개의 field를 포함하는 Size Structure Type 이며, Pixel단위로 컨트롤의 크기를 지정 합니다.


다들 아시겠지만 SizeF 구조체는 실수형 타입 입니다.


모든 윈도우 폼은 폼이 가지고 있는 모든 컨트롤을 표시 할 수 있어야 하며, 이것은 결국 장치 독립적 폼으로 디자인 되어야 한다는 것을 의미 합니다. 

즉 개발자가 가진 노트북에서는 모든 컨트롤을 다 표시 할 수 있으나 다른 모니터로 이동하게 되면 모든 내용이 다 표시 되지 않는 사태가 발생 될 수 있으며 이런 것을 방지 하기 위한 것 입니다. 결국 예전의 모든 해상도에 맞게 또는 모든 모니터 디바이스에 맞게 폼을 다시 디자인 했었을 수도 있었을 것입니다. 이런 일들 정말 힘들고 고된 일들이죠. 저에겐 아직도 장치 독립적 이라는 주제가 어렵게 느껴집니다. 결국 저는 초딩 때 산수 공부를 정말 안한것 같습니다.


프린터는 기본적으로 300 dpi(dot per inch : 인치 당 dot(점) 의 수), 600 dpi, 또는 1200 dpi 와 같은 장치 해상도가 있는 것 처럼 비디오 디스플레이에도 특정한 장치 해상도를 가지고 있습니다. 윈도우 7 까지는 기본 해상도로 96 dpi가 사용 되었으나 윈도우 8 부터는 기본 해상도로 120 dpi가 사용 되고 있습니다.


윈도우 8.1을 설치 하고 난뒤 모든 것들이 전부 크게 보여 참 당혹스러워 했던 기억이 있습니다.


제가 가진 노트북의 Display panel은 물리적으로 15.7 인치의 사이즈 이며 이 사이즈 안에 1920 * 1080 (pixel)으로 이루어 져 있습니다. 


다른 환경에서 같은 것을 경험한다는 것은 참 어려운 일인듯 합니다만 마이크로소프트는 다른 사용자가 각기 다른 디바이스들에서 같은 윈도우 화면을 경험하게 하고자 했던 것 같습니다.


윈도우 8.1에서 이 dpi를 설정 하는 방법을 알아 보도록 하죠.


우선 바탕화면에서 마우스 오른쪽 버튼을 클릭하여, 개인설정을 표시 합니다.




개인 설정이 표시 되면 좌측 하단의 디스플레이를 클릭 합니다.


다음 화면에서 우리는 dpi 설정을 할 수 있습니다.



작게 - 100%(S)                 : 96  dpi (pixel / dot per inch)

보통(M) - 125%(기본값)      : 120 dpi (pixel / dot per inch)

크게 - 150%(L)                 : 144 dpi (pixel / dot per inch)


사용자 지정 크기 조정 옵션을 선택 하면 좀 더 다양한 Scale 을 지정 할 수 있습니다.


Windows Form Program 은 Graphics 클래스의 DpiX 와 Dpi Property를 사용하여, 비디오 디스플레이를 포함한 모든 그래픽 출력 장치의 해상도를 얻을 수 있습니다.


Windows Forms의 기본 글꼴은 약 9 Point 입니다. (포인트는 1/72 인치를 나타내는 측정 단위 입니다.) 이 값은 Font 클래스의 SizeInPoints로 구할 수 있습니다. 


장치 독립적인 프로그래밍을 위한 가장 근본이 되는 기초 이론을 살펴 보았지만.. 역시 이건 너무 어렵네요... 그냥 이런게 있다는 것 정도만.... OTL.....


Microsoft 의 Visual Studio는 AutoScaleDimensions 와 AutoScaleMode Property 를 사용하여 장치 독립적인 기능을 지원하고 있습니다. 이 Property들은 ContainerControl Class에 정의 되어 있습니다.

이 클래스는 Control클래스를 상속 받았으며, Form 클래스는 ContainerControl  클래스를 상속 받습니다.


AutoScaleMode Property 는 AutoCaaleMode Enum Value를 받습니다. 이 열거형은 다음과 같이 정의 되어 있습니다.


public enum AutoScaleMode

    {

        None,

        Font,

        Dpi,

        Inherit

    }


만약 AutoScaleMode 속성을 AutoScaleMode.Font로 설정 한다면, Form 클래스는 폼의 Font 속성에서 지정한 크기 비율(Font 의 크기 비율은 Font.height에 비해 Font.width 는 대략적으로 1/2의 비율 크기를 갖습니다.)에 따라서 모든 크기를 AutoScaleDimresions속성에서 지정한 배율 크기로 조절할 것입니다. 만약 윈도우가 96 DPI의 작은 배율로 설정 되어 있다면, VisualStudio는 다음과 같은 두 문장을 자동으로 추가 할 것입니다.


this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;


만약 디스플레이 해상도를 참조 하여 폼을 디자인 하고 싶다면 다음과 같이 할 수 있습니다.


this.AutoScaleDimensions = new System.Drawing.SizeF(96, 96);

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;


this.AutoScaleDimensions = new System.Drawing.SizeF(120, 120);

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;


아무리 봐도 이건 참 어렵습니다.



'Functional World > C#' 카테고리의 다른 글

널 병합 연산자.....  (0) 2014.12.15
Collection Object Dispose() 쉽게 하기......  (0) 2014.11.12
Form.ActiveForm  (0) 2013.11.07
바이트 배열 취득  (0) 2013.10.01
boxing 에 대한 생각의 오류....  (0) 2013.09.30
Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

어플리케이션의 활성화 폼을 체크 하여야 할 경우가 발생 하였습니다.


어렵지 않은 일이 좀 곤란해져 버렸습니다.


Form.Active 프로퍼티는 직접 접근이 불가하고 


폼이 위치한 곳과 체크하는 곳의어셈블리가 틀려 


Form.ActiveForm은 사용 불가.....


Application.OpenForms를 가지고 FormCollection을 반환 받고 보니 Active상태된 폼을 얻기가 이만 저만...

피곤한 일이 아닌거였습니다.


사실 가져다 확인 할 수 있는 프로퍼티가 없어 보이더군요.


예전 API를 이용해서 확인 하였던 방법은.. 당췌 기억이 나지도 않고.....


사람은 망각의 동물이라더니... 점점 노화 되는 머리는 세월을 이길 수 없나 봅니다.


그래서 약간의 편법을....


 Form frm = Application.OpenForms.Cast<Form>().Last();


이 코드로 마지막 열린 폼을 취득하여, 현재 활성화 된 폼으로 인지 하도록 코딩


이거 참... 세상에 쉬운일이 없습니다.


정상적인 방법이 아니므로 더 좋은 방법이 없을지 고민좀 해야 겠습니다.



Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

static 클래스로 정수형을 바이트 배열로 취득 할 수 있는 클래스 존재.


var bytes = BitConverter.GetBytes(value);

if (BitConverter.IsLittleEndian) { bytes = bytes.Reverse().ToArray(); }



자세한 내용은 

http://msdn.microsoft.com/ko-kr/library/vstudio/system.bitconverter(v=vs.100).aspx


참조.

Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

나는 어쩔 수 없는 초보 인가 보다..


아니면 너무 C++ 포인터에 젖어 있어 그런가.. 당췌 알 수 없지만...


오늘 하나를 또 배웠다...


Int32 v = 5;

Object o = v;

v = 123;


이렇게 코드를 작성 했을 때 단순하게 박싱을 업캐스팅을 이용한 포인터 라고만 이해 한다면 이건 정말 생각의 오류 였던 것이다.


o의 값은 여전히 5 이다.


박싱된 o와 v는 별개 인 것이다.


이렇게 생각 해 보면 몇가지 문제가 있다.


o는 레퍼런스 타입이다. 레퍼런스 타입이라는 것은 언제든 가베지 컬렉터가 수집하여 소거 하여야 하는데, Value 타입으로 부터 파생되었으므로 명시적으로 소거를 할 수 없다. 


더불어 박싱이 일어 나게 된다면 일어나는 만큼 값 복사가 될 것이다.


이는 퍼포먼스 측면에서도 메모리 사용 측면에서도 상당한 스트레스로 작용하게 될 것이다.


예전 무식하게 프로그램을 작성하던... 명시적인 타입의 전달이 역시나, 진리로 느껴지는 순간...


ValueType을 사용하기 싫어진다... 젠장.....

'Functional World > C#' 카테고리의 다른 글

Form.ActiveForm  (0) 2013.11.07
바이트 배열 취득  (0) 2013.10.01
IEnumerator 사용하기 - 기초  (0) 2013.08.11
Generic Collections  (0) 2013.07.15
C# 5.0 async, await  (0) 2013.07.05
Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

열거자를 사용하기 위한 방법이다.


1. IEnumerator를 상속 받는 방법..

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IEnumeratorTest
{
    class myEnumerator : IEnumerator    
    {
        string[] whoareyou;
        int position = -1;

        public object Current
        {
            get { return whoareyou[position]; }
        }

        public bool MoveNext()
        {
            if (position < whoareyou.Length - 1)
            {
                position++;
                return true;
            }
            else return false;
        }

        public void Reset()
        {
            position = -1;
        }

        public myEnumerator(string[] inNames)
        {
            whoareyou = new string[inNames.Length];
            for (int i = 0; i < inNames.Length; i++)
                whoareyou[i] = inNames[i];
        }

    }
}


 종류

 유형 

 기능

 Current

 속성 

 읽기 전용 속성으로 현재 위치의 아이템을 object로 반환 

 MoveNext 

 메서드

 다음 위치로 이동, 다음 아이템 존재 true, 아니면 false 

 Reset

 메서드

 초기 상태로 위치를 설정


2. IEnumerator<T>를 상속 받는 방법.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IEnumeratorTest
{
    class genericEnumerator : IEnumerator<string>
    {
        string[] strPlayer;
        int position = -1;

        public string Current
        {
            get { return strPlayer[position]; }
        }

        public void Dispose() { }

        object System.Collections.IEnumerator.Current
        {
            get { return strPlayer[position]; }
        }

        public bool MoveNext()
        {
            if (position < strPlayer.Length - 1)
            {
                position++;
                return true;
            }
            else return false;
        }

        public void Reset()
        {
            position = -1;
        }

        public genericEnumerator(string[] inNames)
        {
            strPlayer = new string[inNames.Length];

            for (int i = 0; i < inNames.Length; i++)
            {
                strPlayer[i] = inNames[i];
            }
        }
    }
}



 종류

 유형

 기능

 Current

 속성

 IEnumerator로 부터 상속된 속성 현재 위치의 아이템을 Object로 반환

 Current

 속성

 T Current {get;}의 형태로 T로 반환

 Dispose 메서드 파일 스트림과 같은 관리되지 않는 자원을 닫거나 해제할 때 사용

 MoveNext

 메서드

 다음 위치로 이동, 다음 아이템이 있으면 true 없으면 false

 Reset

 메서드

 초기 위치로 설정


Main

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IEnumeratorTest
{
    class Program
    {
        static void Main(string[] args)
        {
            myEnumerator my = 
                new myEnumerator(new string[] { "전우치", "홍길동", "머털도사" });
            while (my.MoveNext())
            {
                string strName = (string)my.Current;
                Console.WriteLine("{0}", strName);
            }


            genericEnumerator str = 
                new genericEnumerator(new string[] { "베트맨", "슈퍼맨", "아이언맨" });
            while (str.MoveNext())
            {
                string strName = (string)str.Current;
                Console.WriteLine("{0}", strName);
            }

            Console.ReadLine();
        }
    }
}



'Functional World > C#' 카테고리의 다른 글

바이트 배열 취득  (0) 2013.10.01
boxing 에 대한 생각의 오류....  (0) 2013.09.30
Generic Collections  (0) 2013.07.15
C# 5.0 async, await  (0) 2013.07.05
Runtime에 클래스 맴버를 취득 하고자 할 경우….  (0) 2013.07.04
Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,

제너릭 컬렉션 이름

기능

List<T>

Array List와 유사한 기능을 수행하는 동적 배열

LinkedList<T>

이중 연결 리스트 구현에 사용

SortedList<TKey, TValue>

키와 값의 쌍으로 구성된 정렬된 리스트

Stack<T>

Last in First out

Queue<T>

First in First out

HashSet<T>

Hash Table을 이용하여, 구별되는 값들의 집합의 구현

SortedSet<T>

정렬된 순서대로 관리되는 집합

Dictionary<TKey, TValue>

HashTable 클래스와 유사하게 키, 값의 쌍으로 저장

SortedDictionary<TKey, TValue>

정렬된 키, 값의 쌍으로 저장한 리스트

 

Sample :

String[] player = { "전우치" , "홍길동", "영구" };

List<string> koreaplayer = new List<string>(player);

foreach (string tt in koreaplayer) Console.WriteLine(tt);

 

 

Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,