C# 2006/12/26 13:21

인덱서(Indexer)

인덱서
  • 클래스의 객체나 구조체의 변수를 배열형식으로 이용할 수있게 해주는 기법.

그 구조는 속성과 유사하며 속성처럼 get 및 set 접근자를 사용한다. 그리고 객체 index인자를 가지며, 객체의 이름 자체를 배열로 이용하기 때문에 this 키워드가 인텍서의 이름으로 사용된다.

사용예~


using System;
using System.Collections;
class SimpleIndexer
{
ArrayList lname = new ArrayList();
public object this[int index]
{
get
{
  if(index > -1 & index<lname.Count)
   return lname[index];
  else
   return null;
}
set
{
  if(index>-1 & index<lname.Count)
   lname[index] = value;
  else if(index == lname.Count)
   lname.Add(value);
  else
   Console.WriteLine("sid[" + index + "] : 입력 범위 초과 에러!!");
}
}
}
class IndexerTest
{
public static void Main()
{
SimpleIndexer sid = new SimpleIndexer();
sid[0] = "hong";
sid[1] = "kim";
sid[2] = "sug";
Console.WriteLine(sid[0]);
Console.WriteLine(sid[1]);
Console.WriteLine(sid[2]);
sid[10] = "park";
}
}
 

하위 클래스에서 상위 클래스의 함수의 동일한 이름을 만드는 것을 오버라이딩 이라고 한다. 이렇게 만들때 오버라이딩 할수 있는 종류에는 두가지가 있다.

new 키워드를 이용한 재정의
virtual,override 키워드를 이용한 재정의

둘의 차이점은 소스로 보자 ^^


using System;
class Base
{
 public void FuncA()
 {
  Console.WriteLine("Base.FuncA");
 }
 public virtual void FuncB()
 {
  Console.WriteLine("Base.FuncB");
 }
}
class Derived: Base
{
 new public void FuncA()
 {
  Console.WriteLine("Derived.FuncA");
 }
 public override void FuncB()
 {
  Console.WriteLine("Derived.FuncB");
 }
}
class Together
{
 public static void Main()
 {
  Derived d = new Derived();
  Base a = d;
  d.FuncA();
  a.FuncA();
  d.FuncB();
  a.FuncB();
 }
}
 



위 프로그램의 결과는

Derived.FuncA
Base.FuncA
Derived.FuncB
Derived.FuncB



new라는 키워드는 하위 클래스에서 상위 클래스의 매서드를 완전히 무시하고 업캐스팅 되었을 때 하위 클래스를 완전히 무시해 버린다. 그리고 virtual과 override는 하위 매서드를 실행해서 클래스의 특징인 다형성을 구현한다.

internal 접근자.

하나의 Assembly 내에서만 접근을 허락하는 접근자이다.

User inserted image





internal접근자를 사용하기 되면 왼쪽 그림과 같이 서로 다른 Assembly에서 접근 하게 된다면 에러가 나게 된다.







protected internal 접근자

internal 접근자를 사용하면 다른 Assembly에서 접근을 할 수 없다. 그렇지만 하위클래스에서 상의 클래스로 접근할 필요가 있을때 protected internal 접근자를 사용하면 Assembly가 비록 다를지라도 상속을 받게 되면 접근할 수 있게 된다.
C# 2006/12/20 15:13

unsafe와 fixed

unsafe 키워드를 알아 보자

일반적으로 C#에서는 CLR이라는 놈이 메모리를 관리 해주기 때문에 메모리에 신경을 별로 쓰지 않아도 알아서 다 해준다. 그렇기 때문에 포인터 처리 차체를 기본적으로 처리 하지 않느다. 그래서 일반적인 C의 * 요놈이나 & 요놈이 처리 되지 않는다. 그런데 그렇다고 포인터 연산을 사용할수 없지는 않는단다.(전혀 몰라던 사실 ㅜㅜ)
CLR이 메모리를 관리 해주면 안전하지만 사람이 관리 하면 불안전해서 붙여진 이름인가 보다 unsafe 라는 키워드 이 키워드를 사용하면 C의 포인터를 처리 할수 있다.


using System;
class UnsafeTest2
{
unsafe static void Swap(int *x,int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
public static void Main()
{
int x = 10;
int y = 20;
Console.WriteLine("Swap Before x:{0} y:{1}",x,y);
unsafe
{
  Swap(&x,&y);
}
Console.WriteLine("Swap After x:{0} y:{1}",x,y);
}
}
 

csc /unsafe UnsafeTest.cs

UnsafeTest
Swap Before x:10 y:20
Swap After x:20 y:10


위의 소스를 보게 되면 unsafe로 선언된 함수나 구역에서는 포인터 처리를 할 수 있다. 음. 여태껏 몰랐던 사실이다. 그리고 컴파일 할 때는 옵션으로 /unsafe 라는 옵션을 넣어 주어야 한다. 그렇지 않으면 Error가 난다.

다음으로 fixed이다. 일단 이 fixed란 놈은 unsafe코드 영역 내부에서 사용되어 진다. 그런데 어떨때 사용되나? 이 fixed라는 놈은 포인터의 값으로 배열이나 혹은 클래스의 멤버를 넘겨 줄수도 있을 것이다. 그런데 일반적인 unsafe문 안에서라도 클래스의 주소를 바로 넘겨 버리면 값을 넘겨주지 못한다. 이런 황당 씨츄에이션이 ㅡ.ㅡ; 어째던 배열이나 클래스 멤버의 주소를 넘겨 줄려면 fixed를 사용해서 값을 넘겨 준다.


using System;
class Point
{
public int x,y;
}
class FixedTest2
{
unsafe static void DoubleSum(int *p)
{
 int a = *p;
 *p = a+a;
}
unsafe static void Main()
{
 Point pt = new Point();
 pt.x = 5;
 pt.y = 6;
 fixed(int *p = &pt.x)
 {
  DoubleSum(p);
 }
 Console.WriteLine("{0} {1}",pt.x,pt.y);
}
}
 



위와 같이 클래스의 멤버 변수 x를 접근 할려고 할때 fixed를 사용하게 된다. 그런데 fixed를 사용하지 않고
DoubleSum(&pt.x); 라고 바로 값을 넘겨 줄 경우

csc /unsafe FixedTest2.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.42 for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727 Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

FixedTest2.cs(21,13): error CS0212: 고정되지 않은 식의 주소는 fixed 문의
       이니셜라이저를 통해서만 가져올 수 있습니다.



위와 같은 에러가 나게 된다. 아마도 CLR이 접근 구성하느 배열 혹은 클래스의 메모리를 C의 스타일대로 접근하려 할때 사용되는 것을 알게 되었다.

constreadonly는 둘다 상수를 선언하기 위해서 사용된다. 그러나 이 둘에는 약간의 차이가 있다. 이 차이점을 알아 보자.

const는 선언과 자동으로 static의 속성을 의무적으로 갖는다. 그렇기 때문에 클래스 이름으로 접근이 가능하다.
그리고 const 접근자는 생성과 동시에 초기값을 주어야 한다. 값을 설정하지 않으면 Error가 나게 된다.

readonly는 일반적인 static과 노멀한 변수와 구분이 된다. 선언에 따라가 다른 속성을 가질수 있다.
그리고 반드시 생성과 동시에 초기값을 줄 필요는 없다. 그리고 단 한번의 값만을 가질수 있게된다. 이 때 이한번의 값은 반드시 생성자에서만 값을 넣울수 있다.


혹 readonly가 한번의 값을 넣을수 있는데 혹시 생성자 아닌곳에서 한번 값을 넣으면 Error가 안날 것 같아서 해보았는데 그 것은 에러가 났다 결국 한번의 설정값을 설정하는것은 생성자에서만 가능하다는 알수 있었다. 그리고 readonly는 static과 일반적인 상용이 구분되니 readonly static 변수의 초기값은 static 생성자에서 설정을 해주어야 할 것이다.

클래스 함수에서 스테틱 멤버필드나 스테틱 함수를 사용할 수 있게 되는데 이 스테틱 멤버필드와 같은 경우에는 스테틱 생성자를 이용하여 멤버들의 값을 초기화 할수 있다. 그렇다면 이 스테틱 생성자는 언제 생성이 될것인가? 메인이 실행되는 시점? 궁금하다.


using System;
class StaticConst
{
public static int sInt=0;
static StaticConst()
{
 sInt = 10;
 Console.Write("sInt=" + sInt + " : static생성자!!!");
}
public StaticConst()
{
}
public static void InitSint(int a)
{
 sInt = a;
}
}
class StaticConstTest
{
public static void Main()
{
 Console.WriteLine("사용하지 않음");
 int a=StaticConst.sInt;
}
}
 



위와 같은 간단한 코드를 만들어 봤다. 그럼 결과는

StaticConst

사용하지 않음
sInt=10 : static생성자!!!



이와 같은 결과가 나왔다. 그렇다면 스테틱 생성자는 사용하지 않음 후 생성자의 메세지가 출력 됐으므로 스테틱 생성자는 스테틱 멤버를 접근하게 되면 스테틱 생성자가 생성됨을 알게 되었다.

참고로 스테틱 생성자의 특징!!
접근제어를 사용할 수 없음.
매개변수를 가질 수 없음.

csc.exe의 컴파일 옵션들이다.

/reference:xxx.dll   닷넷 어셈블리 dll을 링크 시킬때 사용
/out:xxx.exe            실행파일 명을 지정할때 사용
/target:library         exe 로 생성할지 dll로 생성할지에 대한 것을 설정한다.
/unsafe                   안전하지 않은 코드 즉 unsafe문이 들어간 코드는 이옵션을 사용해서 컴파일 해야함.

모든 단어가 길어서 치기 귀찮다면 앞글자 한자만 써도 가능하다.

아직은 이것밖에...
C# 2006/12/10 19:56

C#에서 dll을 링크 3

dll 링크 세번째 이번에는 포인터 ㅡ.ㅡ; 별쓰데 없는것에 다 한다는 생각이 든다. 불현듯 아참 C#은 포인터를 안쓰지?? 라는 생각에서 그럼 포인터를 사용한 dll을 이용할수 있을까나??? 이런 생각이 또 들었다. 아참~~ 이 꼬리에 꼬리는 무는 잡생각들~~

어째던 아래와 같이 dll을 만들었다.


extern "C" __declspec(dllexport)void IntSwap(int * a,int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
extern "C" __declspec(dllexport)void LongSwap(long * a,long * b)
{
long temp;
temp = *a;
*a = *b;
*b = temp;
}
 


포이터의 단골 주제인 Swap이다. 음...

이제는 C#코드인데..... 조금 생각을 해봤다. 과연 포인터의 인자값을 어떻게 넘길것인가에 대한 것. 여러 궁리 끝에 드디어 ref를 이용해서 dll 함수를 쓸수 있게 되었다. 음.. 역시 그럼 이제 C#으로 안되는것은 별로 없네.. 라는 생각이 들었다.


using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace DllPointer
{
  class Program
  {
       [DllImport("DllSwap.dll",CharSet=CharSet.Ansi)]
       public static extern void IntSwap(ref int a,ref int b);
       [DllImport("DllSwap.dll", CharSet = CharSet.Ansi)]
       public static extern void LongSwap(ref long a, ref long b);
       static void Main(string[] args)
       {
           int a = 10;
           int b = 20;
           IntSwap(ref a, ref b);
           Console.WriteLine("a = {0}, b = {1}",a,b);
           long c = 10000000;
           long d = 20000000;
           LongSwap(ref c, ref d);
           Console.WriteLine("c = {0}, d = {1}",c,d);
       }
  }
}
 


User inserted image

C# 2006/12/10 19:30

타 플랫폼에서의 .NET

글출처: http://cafe.naver.com/monodevelop.cafe 남정현(junghyun0816) 
------------------------------------------------------------------
닷넷은 프레임워크라고 하는 구성 요소를 중심 축으로 하여 여러 가지 서비스들을 제공하고 있습니다. 이 프레임워크는 대개의 닷넷 개발자들이 Microsoft 제품 외에는 없다고 단정을 지을 때가 상당히 많은데, 사실은 프레임워크도 종류가 여러가지입니다. Mono는 이러한 것들 중의 한 종류라고 할 수 있습니다.

 

* Microsoft .NET Framework

Windows 환경에서 가장 널리 사용됩니다. Microsoft가 .NET에 관해서 보여주고 싶어하는 것을 가장 빨리 확인할 수 있는 프레임워크이기도 합니다. 현재 공개된 가장 최근의 버전은 2.0 Beta 2이며, 아직은 1.1 버전을 널리 사용합니다. 소스 코드는 사용하실 수 없지만 무료로 다운로드하실 수 있습니다.

 

* Microsoft Rotor Framework

.NET Framework에 대한 얼터너티브 버전으로, Mac OS X, BSD 계열 유닉스, Windows를 대상으로 배포 중인 프레임워크입니다. .NET Framework의 버전에 맞춰서 같이 발매되는데, .NET Framework 2.0의 정식 버전이 발표되면 마찬가지로 이 프레임워크의 새 버전이 나옵니다. 이 프레임워크는 오픈 소스이며, 소스 코드로 제공됩니다.

 

* Mono Framework(http://www.mono-project.com/)

원래 Ximian에서 처음 개발을 시작한 오픈 소스 프레임워크입니다. Linux, Unix, Mac OS X, Windows를 대상으로 개발되는 프레임워크입니다. Microsoft .NET 영역에서 제공되지 않는 툴킷을 다수 기본 제공하며 많은 수의 닷넷 계열 오픈 소스 프로젝트들이 이 프레임워크를 기준으로 작성됩니다. GTK#, COCOA#, 다수의 ADO .NET 어댑터 (SqLite, MySQL, ...)들을 기본 제공합니다.

 

* DotGNU Framework

GPL 라이센스를 따르는 오픈 소스 프레임워크입니다. Mono에 비해 늦게 시작하였지만 Mono와는 달리 성능에 상당히 초점을 맞추고 개발하는 프레임워크입니다. 이 프레임워크가 지향하는 환경은 리눅스에서 네이티브 모드로 닷넷 어플리케이션들을 구동하는 것이라 합니다.

 

현재까지 알려진 프레임워크는 이 정도입니다. 진행하시고자 하는 프로젝트나 학습 방향에 맞는 프레임워크와 개발 도구를 선택하시는 것은 본인의 몫이기에 어느 것이 더 좋다고 이야기할 수는 없겠습니다.
------------------------------------------------------------------



좀더 자세한 사항을 알고자 한다면 MONO Framework의 개발 까페인 http://cafe.naver.com/monodevelop.cafe 를 참고하시기 바랍니다.


참고로 Rotor Framework이라고 알려져 있는 것은 SSCLI2.0으로 나와 있으며 FreeBSD에만 포팅이 되는 것으로 알고 있는데 정확치는 않습니다. 다음 사이트를 참고하시기 바랍니다.

http://research.microsoft.com/sscli/ 
C# 2006/12/08 12:42

C#에서 dll을 링크 2

앞의 예제는 콘솔 프로그램으로 dll을 사용해 봤고 지금것은 WinForm을 사용하였다. 그래서 dll로 MessageBox함수를 수행하는 dll을 만들었다.


extern "C" __declspec(dllexport)int MsgBox(HWND hWnd,LPCTSTR lpTest,LPCTSTR lpCaption,int uType)
{
    return MessageBox(hWnd,lpTest,lpCaption,(UINT)uType);
}
 



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace DllTest
{
   public partial class Form1 : Form
   {
       [DllImport("MyDll.dll", CharSet = CharSet.Ansi)]
       public static extern int MsgBox(IntPtr hWnd,string lpTest,string lpCaption,int uType);
       public Form1()
       {
           InitializeComponent();
       }
       private void button1_Click(object sender, EventArgs e)
       {
           MsgBox(this.Handle, "메세지", "타이틀", 0);
       }
   }
}
 


User inserted image


위의 메세지 박스는 dll을 사용하였다.


div>