본문 바로가기
[ Program ]/C#

어트리뷰트와 기타 기능

by 관이119 2012. 9. 18.
출처 한섬 | 유향버들
원문 http://blog.naver.com/shopin00/100010624505

▣ 어트리뷰트

- 어트리뷰트는 프로그램의 정보나 부가적인 기능을 위해 프로그램과는 별도로 지장하는 메타 데이터(meta

data)라고 할 수 있다

- C#이 실행될 때 객체 지향 프로그래밍 언어의 특성을 CLR에서 실행할 수 있도록 도와 주는 특수한

목적의 주석이다

- 프로그램의 실행에 직접 관련되지는 않지만, C#의 실행을 도와 주는 코드이다

- 어트리뷰트란 클래스, 인터페이스, 구조체와 같은 객체 지향 프로그래밍 언어의 특성을

C# 프로그램이 실행될 때 실행환경인 CRL에서 사용할 수 있도록 도와 주면서 메타 정보를 전달해

주는 특수한 목적의 주석(comment)이라고 할 수 있다

- 코드의 수행 여부를 결정하는 전처리기 기능, 다른 언어로 작성된 DLL이나 COM과 같은 외부 라이브러리

를 호출하는 기능

- 디버깅, 릴리스와 같이 프로그램의 개발단계에 따라 코드들을 분류해서 작성하고 실행할 수 있다


★ 메타 데이타(meta data)

: 프로그램의 실행과 적접적인 관련을 없지만, 개발자의 프로필이나 개발에 대한 여러가지 정보들을

기록해 놓은 데이타, 메타데이타는 하나의 프로그램을 여러명의 개발자들이 공동으로 작업하는

경우 유용하다


1. 조건 어트리뷰트

- 다양한 경우에 따라 특정한 코드를 실행할 수 있도록 프로그램을 제어하는 것을 의미

- 프로그램이 개발단계이냐, 테스트 단계이냐 또는 릴리스 단계이냐에 따라 특정코드의 실행 여부를

결정해서 실행 할 수 있다



# define 심벌

// 심벌을 정의한다

# undef 심벌

// 심벌의 정의를 해제한다

[Conditional 심벌]

// 심벌과 관련된 코드 실행


/* 15장 ExamConditionalAttribute
* 조건 어트리뷰트에 대한 예제입니다. */

#define DEBUG


using System;
using System.Diagnostics;

class MyClass
{
[Conditional("DEBUG")]
public void DisplayDebugInfo()
{
Console.WriteLine("디버그 정보를 출력합니다.");
}

[Conditional("RELEASE")]
public void DisplayReleaseInfo()
{
Console.WriteLine("릴리스 정보를 출력합니다.");
}
}

class TestForConditionalAttribute
{
static public void Main()
{
Console.WriteLine("조건 어트리뷰트에 대한 예제 프로그램입니다.");
Console.WriteLine();

MyClass A = new MyClass();

A.DisplayDebugInfo();
A.DisplayReleaseInfo();

Console.ReadLine();
}
}

- 조건 어트리뷰트 사용 관련 주의사항

① 조건 어트리뷰트로 제어하는 메소드의 리턴형은 void형이다

② 인터페이스로 재정의하는 메소드는 조건 어트리뷰트에서 사용할 수 없다

③ 가상 메소드로 오버라이드하는 메소드는 조건 어트리뷰트에서 사용할 수 없다

2. Obsolete 어트리뷰트

- 과거에 사용했지만 현재는 이름이 바뀌어 사용하지 않거나 기능이 변경된 메소드를 사용할 경우 오류

메세지 출력 해준다

- [Obsolete "메시지"]


/* 15장 ExamObsoleteAttribute
* Obsolete 어트리뷰트에 대한 예제입니다. */

using System;
using System.Diagnostics;

class MyClass
{
[Obsolete("이 메소드는 옛날 버전입니다. 새 버전을 사용해주세요.")]
public void OldMethod()
{
Console.WriteLine("구버전의 메소드입니다.");
}

public void NewMethod()
{
Console.WriteLine("최선 버전의 메소드입니다.");
}
}

class TestForObsoleteAttribute
{
static public void Main()
{
Console.WriteLine("조건 어트리뷰트에 대한 예제 프로그램입니다.");
Console.WriteLine();

MyClass A = new MyClass();

A.OldMethod();
A.NewMethod();

Console.ReadLine();
}
}

3. DIIImport 어트리뷰트

- C#에서는 기존의 언어로 제작된 DLL을 사용하기 위해 DllImport 어트리뷰트를 제공하고 있다

- 다른 언어로 작성된 DLL들은 C#이나 닷넷에서 제어할 수 없는 비관리 코드(unmanaged code)이다

- 비관리 코드로 되어있는 DLL을 관리 코드인 C#에서 사용하려면, System.Runtime.InteropServices

네임스페이스를 사용한다음 DllImport 어트리뷰트를 사용해서 해당 DLL 파일을 로딩한다

- [DllImport "DLL의 이름"]의 형식으로 사용

- DllImport 어트리뷰트로 연결된 DLL의 함수는 반드시 public static extern으로 정의해야 한다


★ 관리코드와 비관리 코드

: 관리코드 => C#의 실행 환경인 CLR에서 실행중인 오류가 발생하는지 혹은 잘못된 연산을 수행하는지를

계속 감시할 수 있는 코드 , 예외처리와 같은 방법으로 오류가 발생하기전에 막을 수있다

비관리 코드 => 기존의 다른 프로그래밍 언어로 작성된 것으로, C#과 함께 사용해야만 하는 코드로

CLR에서 감시하거나 관리할 수 없기 때문에 비관리 코드라고 한다

/* 15장 ExamDllImportAttribute
* DllImport 어트리뷰트에 대한 예제입니다. */

using System;
using System.Runtime.InteropServices;

class TestForDllImportAttribute
{
[DllImport("user32.Dll")]
public static extern int MessageBox(int id, string text, string title, int type);

static public void Main()
{
Console.WriteLine("DllImport 어트리뷰트에 대한 예제 프로그램입니다.");
Console.WriteLine();

int ret;

ret = MessageBox(0, "메시지 박스 테스트", "DllImport Attribute", 1);
if(ret == 1)
MessageBox(0, "메시지 박스 테스트", "DllImport Attribute", ret);
else
MessageBox(0, "메시지 박스 테스트", "DllImport Attribute", ret);

Console.ReadLine();
}
}


▣ Unsafe Code

- unsafe code는 비안전 코드란 의미이다

- 포인터와 같이 CLR(Common Language Runtime)에서 관리가 불가능한 코드를 비안전 코드라 한다

- 포인터는 임의의 객체의 주소를 가키는 변수로, 프로그래머가 원하는 시스템의 모든 주소에

접근할 수 있다

- 개발자가 포인터를 잘못사용해서 원도우 시스템 영역의 특정 메모리 부분을 덮어쓰거나 수정하게

되면, 시스템 자체를 망가뜨릴 수 있다 (안전하지 못한 코드이다)


1. 포인터

- 주소라고 정의할 수 있다

- 데이터형 *변수의 이름;

- & 연산자는 변수의 주소값을 나타내는 연산자 이다


int number = 100;

int *ptr = &number; // 주소를 정의할 수 있는 point 변수 ptr에 number의 주소값을 나타낼수 있다

*ptr = 10 // ptr변수가 가지고있는 주소에 값 10을 입력하라는 의미이다


2. C#에서 포인터 사용하기

- C#에서 포인터를 사용해서 프로그램을 작성하면, 기존의 다른 프로그래밍 언어보다 더 위험하다

왜냐하면 C#의 CLR에는 사용하지 않는 메모리를 자동으로 해제해 주는 가비지 컬렉션 기능이 있기때문

- unsafe 키워드를 사용해 포인터를 사용하는 코드의 블럭을 표시한다

- unsafe 키워드로 비안전 코드를 표시해두면 CLR에서 관여하지 않아서 포인터에 할당된 메모리를 해제하기

전까지 CLR에서 해제하는 것을 막을 수 있다

/* 15장 ExamUnsafeCode1
* Unsafe Code에 대한 첫 번째 예제입니다. */

using System;

class TestForUnsafeCode
{
unsafe public static void Main()
{
Console.WriteLine("Unsafe Code에 대한 첫 번째 예제 프로그램입니다.");
Console.WriteLine();

int Number = 100;
int *ptr;
ptr = &Number;

Console.WriteLine("포인터 ptr의 값은 : " + *ptr);

*ptr = 10;

Console.WriteLine("포인터 ptr의 값은 : " + *ptr);
Console.ReadLine();
}
}

★ - 먼저 빌드 옵션에서 unsafe라는 옵션을 설정해 줘야 한다

: 프로젝트의 속성 '페이지에서 안전하지 않는 코드 블록 허용' 항목에 True로 설정


- 클래스나 구조체의 멤버들은 정수형이나 부동 소수점형 등과 같이 일반 데이터형이어야 한다

- string이나 기타 C#에서 제공하는 관리 데이터형을 사용할 수 없다

- C#에서 제공하는 관리 데이터형인 string이나 클래스, 인덱스, 프로퍼티등을 멤버로 정의하는 클래스는

포인터를 사용해서 접근할 수 없다


/* 제 15 장 ExamUnsafeCode2
* Unsafe Code에 대한 두 번째 예제 프로그램입니다. */

using System;

public struct MyData
{
public int ID;
public int Age;
}


class TestForUnsafeCode2
{
unsafe public static void Main()
{
Console.WriteLine("Unsafe Code에 대한 두 번째 예제 프로그램입니다.");
Console.WriteLine();

MyData Data = new MyData();
Data.ID = 1234;
Data.Age = 32;

MyData *ptrData = &Data;

Console.WriteLine("제 ID는 {0}이며 , 나이는 {1}살입니다", ptrData->ID , ptrData->Age);
Console.ReadLine();
}
}

3. fixed 키워드

- unsafe 코드블록 안에서 fixed 키워드를 이용해 강제로 해당 포인터에서 가비지 컬렉션을 하지 않도록

해야 한다

- fixed 키워드를 사용하면, 자동으로 가비지 컬렉션이 실행되어도 fixed 키워드로 보호된 포인터에

할당된 메모리는 해제되지 않는다

/* 15장 ExamFixed
* fixed 키워드에 대한 예제입니다. */

using System;

public class MyClass
{
public int num;

public MyClass(int a)
{
num = a;
}
}

class TestForFixed
{
unsafe public static void Main()
{
Console.WriteLine("fixed 키워드에 대한 예제 프로그램입니다.");
Console.WriteLine();

MyClass Obj = new MyClass(100);

fixed(int *ptr = &Obj.num)
{
Console.WriteLine("Obj.num의 초기값은 : " + *ptr);
*ptr = 10;
Console.WriteLine("Obj.num의 변경 후 값은 : " + *ptr);
}

Console.ReadLine();
}
}

▣ 런타임 데이터형 연산자

- 프로그램의 실행중에 데이터형을 확인할 수 있다

- 프로그램이 실행중에도 데이터형을 변환할 수 있으므로 폭넓은 데이터형을 사용할 수 있다


1. is 연산자

- 임의의 데이터가 어떤 데이터형에 속해 있는지 검사

- 결과값은 True나 False로 나타난다


변수 is 데이터형


/* 15장 ExamIsOperator
* is 연산자에 대한 예제입니다. */

using System;

class GrandParent
{
public GrandParent()
{
Console.WriteLine("GrandParent 클래스의 생성자입니다.");
}
}

class Parent : GrandParent
{
public Parent()
{
Console.WriteLine("Parent 클래스의 생성자입니다.");
}
}

class Child : Parent
{
public Child()
{
Console.WriteLine("Child 클래스의 생성자입니다.");
}
}

class TestForIsOperator
{
public static void Main()
{
Console.WriteLine("is 연산자에 대한 예제 프로그램입니다.");
Console.WriteLine();

GrandParent A = new GrandParent();
Console.WriteLine();

Parent B = new Parent();
Console.WriteLine();

Child C = new Child();
Console.WriteLine();

if(A is GrandParent)
Console.WriteLine("객체 A는 GrandParent의 객체입니다.");
if(B is GrandParent)
Console.WriteLine("객체 B는 GrandParent의 객체입니다.");
if(C is GrandParent)
Console.WriteLine("객체 C는 GrandParent의 객체입니다.");
if(!(B is Child))
Console.WriteLine("객체 B는 Child의 객체가 아닙니다.");
else
Console.WriteLine("객체 B는 Child의 객체입니다.");

Console.ReadLine();
}
}



2. as 연산자

- is 연산자가 데이터형을 확인하는 연산자라면, as 연산자는 데이터형을 변환하는 연산자이다

- 형 변환 코드인 '(데이터형)변수'의 형식과 같은 기능을 수행

- as 연산자는 형 변환에 성공하면 해당 데이터형을 결과값으로 돌려주고, 형 변환에 실해하면

null을 결과값으로 돌려준다


/* 15장 ExamAsOperator
* as 연산자에 대한 예제입니다. */

using System;

class GrandParent
{
public GrandParent()
{
Console.WriteLine("GrandParent 클래스의 생성자입니다.");
}
}

class Parent : GrandParent
{
public Parent()
{
Console.WriteLine("Parent 클래스의 생성자입니다.");
}
}

class Child : Parent
{
public Child()
{
Console.WriteLine("Child 클래스의 생성자입니다.");
}
}

class TestForAsOperator
{
public static void Main()
{
Console.WriteLine("as 연산자에 대한 예제 프로그램입니다.");
Console.WriteLine();

GrandParent A = new GrandParent();
Console.WriteLine();

Parent B = new Parent();
Console.WriteLine();

Child C = new Child();
Console.WriteLine();

GrandParent D;
D = B as GrandParent;
if(D != null)
Console.WriteLine("D의 as 형 변환");
Parent E;

E = C as Parent;
if(E != null)
Console.WriteLine("E의 as 형 변환");

if(A is GrandParent)
Console.WriteLine("객체 A는 GrandParent의 객체입니다.");

if(D is Parent)
Console.WriteLine("객체 D는 Parent의 객체입니다.");
else
Console.WriteLine("객체 D는 Parent의 객체가 아닙니다.");

if(E is Child)
Console.WriteLine("객체 E는 Child의 객체입니다.");
else
Console.WriteLine("객체 E는 Child의 객체가 아닙니다.");

Console.ReadLine();
}
}

3. typeof 연산자

- 데이터형의 정보를 결과값으로 돌려주는 연산자이다

- 클래스의 멤버나 메소드에 대한 정보를 제공하는 것이 typeof 연산자이다


type 변수의 이름 = typeof(클래스나 데이터형의 이름)


/* 15장 ExamTypeOfOperator
* typeof 연산자에 대한 예제입니다. */

using System;
using System.Reflection;

public class MyClass
{
public int num;

public string Name;

public void MyMethod1()
{

}

public int MyMethod2()
{
return 1;
}
}

class TestForTypeOfOperator
{
public static void Main()
{
Console.WriteLine("typeof 연산자에 대한 예제 프로그램입니다.");
Console.WriteLine();

Type t = typeof(MyClass);

MethodInfo[] x = t.GetMethods();
foreach (MethodInfo xtemp in x)
{
Console.WriteLine(xtemp.ToString());
}

Console.WriteLine();

MemberInfo[] x2 = t.GetMembers();
foreach (MemberInfo xtemp2 in x2)
{
Console.WriteLine(xtemp2.ToString());
}

Console.ReadLine();
}
}

 

'[ Program ] > C#' 카테고리의 다른 글

C# NameSpace 총정리  (0) 2012.09.18
C#.NET 에서 엑셀 파일 읽어들여 dataGrid에 출력  (0) 2012.09.18
애트리뷰트(Attribute)  (0) 2012.09.18
【 C# 】 Attribute  (0) 2012.09.18
C# "LC.exe"이(가) -1 코드에서 끝났습니다.  (0) 2012.09.18

댓글