▣ 어트리뷰트
- 어트리뷰트는 프로그램의 정보나 부가적인 기능을 위해 프로그램과는 별도로 지장하는 메타 데이터(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 |
댓글