2008. 10. 3. 17:21

[펌] 어트리뷰트(Attribute)


 어트리뷰트

Attribute는 클래스안에 메타정보를 포함 시킬수 있는 기술로서 클래스, 데이터 구조, 열거자 그리고 어셈블리와 같은 프로그래밍적 요소들의 실행시 행동에 대한 정보를 기술 할 수 있다.

다음과 같은 프로그래밍 요소에 대해 어트리뷰트를 사용 할 수 있다.
어셈블리, 모듈, 클래스, 구조체, 열거형변수, 생성자, 메소드, 프로퍼티, 필드, 이벤트, 인터페이스, 파라미터, 반환값, 델리게이트

어트리뷰트 역시 클래스의 일종이다.

어트리뷰트의 문법은 다음과 같다.
[attribute(positional_parameter, name_parameter = value, …) ]
파라미터에는 두 종류가 있는데 하나는 위치지정 파라미터로 반드시 들어와야 한다. 명명파라미터(name_parameter)는 꼭 필요하지는 않은 구조를 가지면 어트리뷰트 안에 추가적인 정보를 넣을 때 이용한다.

예를들면

[AdditionalInfo(“2004-01-01”)]
public class Test { ..}

원하는 프로그래밍 요소 위에 Attribute를 써주면 그곳에 Attribute가 배정되는 것이다.

1.Conditional Attribute
C# 디버깅을 지원하기 위해 Conditional Attribute를 사용 할 수 있다. Conditional Attribute는 사용자가 정의 한 값에 의해서 해당 메소드를 실행 하도록 한다.

#define SOUNDCARD // 이 부분을 지운 후 실행 해 보자
using System;
using System.Diagnostics;

class Test
{
        //Conditional Attribute인 경우 지정된 위치지정 파라미터가 정의 되어
        //있을때 실행이 되는 것이다.
        [Conditional ("SOUNDCARD")]
        static void print()
        {
                Console.WriteLine("도레미...");
        }

        static void Main()
        {
                print();
        }
}

위 예제에서 #define SOUNDCARD 부분을 지우지 않은 상태에서는 도레미... 가 정상적으로 출력 되지만 지운 상태에서는 출력 되는 않는다.

Conditional Attribute는 클래스나 구조체 안에 있는 메소드 에서만 사용 할 수 있다. 또 그 메소드는 void 형 이어야 한다. 다음의 예문처럼 메소드에 대해 여러 Conditional Attribute를 붙이게 되면 그 중 하나만 위치지정 파라미터가 정의 되어 있어도 그 메소드를 실행 시킨다.

만약 두개의 Conditional Attribute를 모두 만족해야 메소드를 실행 할려면 아래와 같은 방법을 이용하면 된다.

[Conditional(“MODEM”), Conditional(“ADSL”)]
static void print() { .. }

#define SOUNDCARD
#define SPEAKER

using System;
using System.Diagnostics;

class Test
{
        
        [Conditional ("SOUNDCARD")]
        static void isSound()
        {
                isSpeaker();
        }

        [Conditional ("SPEAKER")]
        static void isSpeaker()
        {
                Console.WriteLine("음악을 들을 수 있습니다...");
        }

        static void Main()
        {
                isSound();
        }
}

[결과]
음악을 들을 수 있습니다...

2.DllImport 어트리뷰트
DllImport Attribute는 C#안에서 Unmanaged Code를 사용 할 수 있게 한다. Unmanaged Code란 닷넷 환경밖에서 개발된 코드를 가리킨다. DllImport Attribute는 System.Runtime.InteropServices 네임스페이스 안에 정의 되어 있다. 사용방법은 위치지정 파라미터로 사용 할 DLL 파일을 인자로 넘겨 주면 된다.

using System;
using System.Runtime.InteropServices;

class Test
{
        //User32.dll 파일안의 MessageBox 함수를 불러와서 사용하는 예이다. DllImport Attribute를
        //이용하여 사용할 코드가 포함되어 있는 DLL을 넘겨주고 extern 키워드를 통해 사용하려고 하는
        //메소드가 외부에 있음을 알린다. 이렇게 하면 닷넷 환경 밖에서개발된 코드들도 C#안에서 쓸수 있다.
        [DllImport("User32.Dll")]
        public static extern int MessageBox(int h, string m, string c, int type);

        static void Main()
        {
                MessageBox(0, "Hello!", "In C#", 0);  //다이얼로그 창의 타이블이 "In C#" 이며 내용은 "Hello"
        }
}


3.Custom Attribute의 정의

-어트리뷰트의 범위 지정

앞에서 Conditional Attribte는 메소드에만 붙일 수 있다고 했다. 그렇다면 사용자가 만든 어트리뷰트에 대해 어떤 곳에서만 붙일 수 있게 하는 방법은 없을까? AttributeUsage를 이용해서 사용자가 정의한 데이터 형에만 어트리뷰트를 붙일 수 있다.

[AttributeUsage(AttrbuteTargets.Method)]
public class AdditionalInfo { … }

AttributeUsage 역시 Attrbute 이며 사용자가 정의할 어트리뷰트 앞에 사용됨으로서 범위를 지정 할 수 있다. Method 이외에 AttrbuteTargets.Class, AttrbuteTargets.Delegate, AttrbuteTargets.Interface, AttrbuteTargets.Propert, AttrbuteTargets.Construct 등등을 사용 할 수 있다.

만약 여러 개의 데이터 형에 붙일려면 ‘|’를 이용하면 된다.

[AttributeUsage(AttrbuteTargets.Method | AttrbuteTargets.Delegate)]
public class AdditionalInfo { … }

또한 모든 데이터 형에 붙이는 것을 가능하게 할려면 AttrbuteTargets.All 이라고 해 주면 된다.

-어트리뷰트 클래스 선언

간단히 클래스에 대한 제작자, 업데이트 날짜, 최신 버전을 다운 받을 수 있는 곳등의 정보를 담을 수 있는 어트리뷰트를 만들어 보도록 하겠다. 다른 클래스를 만드는 것처럼 비슷하게 클래스를 작성 하면 어트리뷰트가 구현된다. 모든 어트리뷰트는 System.Attribut로부터 상속 받는다. 즉 보통 클래스를 선언하는 똑 같은 방법으로 선언하고 다만 System.Attriute로부터 상속을 받으면 그 클래스가 어트리뷰트가 되는 것이다. 일반 클래스와 구분하기 위해 접미사로 ‘Attribute’를 붙일 것을 권고 한다.

어트리뷰트도 클래스 이므로 생성자가 존재 한다. 다만 어트리뷰트는 하나의 생성자만 가질 수 있다. 즉 생성자 오버로딩이 불가능 하다. 그럼 추가로 받아야 하는 정보들은 어떻게 처리 할까? 어트리뷰트에서는 생성자에서 꼭 집어 넣어야 하는 데이터는 위치지정 파라미터로 받고 부가적인 데이터는 명명 파라미터를 통해 받아 들임으로서 문제를 해결 한다.

[예제]
using System;

[AttributeUsage(AttributeTargets.Class)]
public class AdditionalInfoAttribute: Attribute
{
        //생성자에 있는 두개의 인자는 위치지정 파라미터 이다.
        //즉 위치지정 파라미터는 클래스에 어트리뷰트를 붙일때 반드시 넘겨 줘야 한다.
        //항상 생성자에서 값을 넘겨 주게 되어 있으므로 name, update인 경우 Property에서
        //set이 없다.
        public AdditionalInfoAttribute(string name, string update)
        {
                this.name = name;
                this.update = update;
        }

        public string Name
        {
                get { return name; }
        }

        public string Update
        {
                get { return update; }
        }

        public string Download
        {
                set { download = value; }
                get { return download; }
        }

        string name;
        string update;
        string download;
}

// 아래의 경우처럼 위치지정 파라미터는 생성자에 값을 그대로 전달하지만 명명 파라미
// 터는 파라미터 이름에 값을 대입하여 생성자에 넘겨야 한다.
[AdditionalInfo(“jclee”,’2004-01-01”, Download = http://www.oraclejava.co.kr)]
class Test { … }


클래스에 어트리뷰트를 붙였다면 반대로 클래스로부터 어떤 어트리뷰트들이 붙어 있는지 아는 하는 방법도 있어야 할 것이다. 바로 전 예제에서 Test라는 클래스에 어트리뷰트를 붙였는데 반대로 Test라는 클래스로부터 어트리뷰트 정보를 알아내는 방법을 예제를 통해 보도록 하자.

public class AttrInfo
{
        public static void Main()
        {
                Type type = typeof(Test);

                foreach(Attribute attr in type.GetCustomAttributes(true))
                {
                        AdditionalInfoAttribute info = attr as AdditionalInfoAttribute;

                        if (info != null)
                        {
                                Console.WriteLine("Name={0}, Update={1}, DownLoad={2}", info.Name, info.Update, info.Download);
                        }
                }
        }
}

4.사용자정의 어트리뷰트의 처리 과정

-어트리뷰트 클래스를 찾는다.
-어트리뷰트의 범위를 체크 한다.
-어트리뷰트의 생성자를 체크 한다.
-객체의 인스턴스를 생성 한다.
-명명 파라미터들을 체크 한다.
-명명 파라미터 값으로 필드나 프로퍼티의 값을 설정 한다.
-어트리뷰트 클래스의 현재 상태를 저장한다.

5.Multiple Attribute의 사용
한 개의 프로그래밍 요소에 한 개 이상의 어트리뷰트를 붙일 수 있다.

public class Csharp {
        [Conditional(“CLR”)]
        [FAQ(http://www.help.com/chapter1)]
public void chapter1() { … }
}

한 개의 프로그래밍 요소에 여러 개의 어트리뷰트를 붙일 수 있지만 앞에서 만든 AdditionalInfoAttribute를 아래 처럼 중복해서 사용하면 오류가 발생 한다.

[AdditionalInfoAttribute(“jclee”,”2004-01-01”, Download=http://www.oraclejava.co.kr)]
[AdditionalInfoAttribute(“tatata”,”2004-02-01”, Download=http://www.oraclejava.co.kr)]
class OracleJava { … }

어트리뷰트는 기본적으로 한 어트리뷰트에 한 개의 인스턴스만 사용 가능하지만 AllowMultiple을 true로 지정하면 위에서와 같이 같은 어트리뷰트를 여러 개 사용 가능하다.


6.어트리뷰트로부터 값 얻어오기
-클래스 메타 데이터
여기서는 Reflection을 이용하여 값을 얻어오는 것을 살펴 보도록 하자. 닷넷 프레임 웍에서는 메타데이터를 검사 할 수 있는 클래스들이 포함된 System.Reflection 이라는 네임스페이스를 제공 하고 있다. 이 Reflection 네임스페이스 안에 있는 MemberInfo 라는 클래스는 클래스의 어트리뷰트를 알아볼 때 유용하게 사용 될 수 있다. System.Type 객체의 GetMembers 라는 메소드를 적절히 구사하여 클래스 메타데이터 를 조사 할 수 있다.

System.Reflection.MemberInfo[] members;
Members = typeof(MyClass).GetMembers();


-어트리뷰트의 정보 얻기
MemberInfo 객체는 GetCustomAttributes 라는 메소드를 가지고 있다. 이 메소드는 모든 어트리뷰트의 정보를 배열로 알아 낼 수 있다. 이렇게 알아낸 정보를 반복문을 이용하여  어트리뷰트를 조사 할 수 있다.

 

출처 :  http://cafe.naver.com/itclean.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=1098

2008. 10. 3. 17:20

[펌] CTS(Common Type System)와 C#의 자료형(Value-Type, Reference-Type)

CTS(Common Type System

----------------------------

• CTS supports object-oriented and Procedural languages.

• CTS supports both value and reference types

 

좀더 알아보면 CTS 는 닷넷 프레임워크에서 동작하는 모든 프로그래밍 언어(C#, VB.Net, J#)들이 쪽같은 데이터형식을 사용하도록 해주는 것입니다.

(System.Int32라는 클래스는 CTS에서 제공하는 int 형입니다. 이것은 닷넷에서의 어떠한 개발언어에서도 사용이 가능 합니다.)

모든 데이터형식들은 기본적으로 객체에서 파생되었으며 Value type 은 객체 형식을 포장 (sealing) 해 놓은 개념 입니다.

 

-----------------------------

Value-Type, Reference-Type

-----------------------------

Value-Type

CTS 에서는 value type 과 reference type 을 지원하는데 Value type 변수들은 데이터를 직접 가지고 있습니다 .예를들어 int i=10 이라고 쓰면 i 변수에는 10 이 직접 들어 있는 것입니다. int j=i 라고 하면 i 의 값이 j에 복사되어 들어 가는 것입니다.(다아시는거죠^^), 자바에서의 기본 자료형과 같은 겁니다. Value-Type은 Built-in Type과 User-Defined Type 두가지가 있습니다. int, long, float, double 등은 Built-in Type 이고 struct, enum등은 User-Defined Type 입니다.

 

Reference-Type

데이터를 직접 저장하는 것이 아니라 레퍼런스(참조값)을 저장 합니다.(Store references to their data) 그러므로 두개의 레퍼런스형 변수는 같은 데이터(오브젝트)를 지칭하는 것이 가능 합니다.( Two reference variables can reference same object) 물론 같은 것을 서로 쳐다 볼수 있으므로 한쪽에서 변경을 하면 다른쪽은 스스로 변경을 안했어도 나중에 값을 꺼내 보면 당연히 바뀌어져 있겠죠^^;(Operations on one can affect another)

 

-------------------------------

Built-in Data Type

-------------------------------

정수형

예약어 구조체형식 크기 (Bit) 범위
sbyte System.Sbyte 8 -128~127
byte System.Byte 8 0~255
short System.Int16 16 -32,768~32,767
ushort System.UInt16 16 0~65,535
int System.Int32 32 -2,147,483,648 ~2,147,483,647
uint Systen.UInt32 32 0~4,294,967,295
long System.Int64 64 -(2^63) ~ 2^63-1
ulong System.UInt64 64 0~ 2^64-1

 

실수형, 기타

예약어 구조체형식 크기 (Bit) 범위
실수형
float System.Single 32 1.5x10^-46 ~3.4x10^38
double System.Double 64 5.0x10^-324 ~1.7x10^308
decimal System.Decimal 128 1.0x10^-28 ~7.9x10^28
기타
char System.UInt16 16 유니코드 1 자
bool System.Int32 1 0 또는 1

 

Boolean

boolean type 이 가질 수 있는 값은 true 와 false 입니다. 예 ) bool b = true --> true 는 1 과는 다르며 , 마찬가지로 false 는 0 과는 다릅니다. (C 에서는 TRUE, FALSE 를 #define 을 통해 정의하여 사용 했었습니다.. 정수를 암묵적으로 boolean 형으로 사용한 것이죠.), true 와 false 로 산술 연산을 할 수 없으며 오로지 논리 연산자를 가진 수식에 대해서만 사용가능 합니다.

 

변수 선언 하는 방법

int itemCount;

int itemCount , employeNumber; ( Possible to declare Multiple variables in one)

int employeeNumber; employeeNumber = 23;

int employeeNumber= 23;

또한 Charater형은 다음과 같이 선언 합니다. char middleInitial= ‘J'; C#은 유니코드를 사용하며 char형은 한 문자를 저장하는데 사용 합니다.

Itemcount = Itemcount + 40; --> ItemCount += 40; --> 이건 다아시죠...

 

연산자(Operator)

구분 연산자
기본 연산자 (x), ., f(x), a[x], x++, x--, new, typeof, sizeof, checked, unchecked
단항 연산자 +, -, !, ~, ++x, --x
산술 연산자 +, -, *, /, %
쉬프트 연산자 <<, >>
비교 연산자 <, >, <=, >=, is
비트 연산자 &, ^, |
논리 연산자 &&, ||
조건 연산자 ?:
할당 연산자 =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=

 

[isOperator 예제] is연산자는 런타임시 주어진 타입과 객체가 서로 호환이 되는지를 검사하는 연산자 입니다. 또한 as 연산자는 Type을 변환하는데 변환이 되면 변환 시키고 변환이 안되면 NULL을 돌려 줍니다...(참고하세요~)

//is 연산자 예제
using System;

class isOperator {
static void Main() {
//C#은 모든 타입을 객체로 처리한다.
//System.Int32의 BaseType은 System.ValueType이다.
//System.Object > System.ValueType > System.Int32
int i=0;
object o;
Console.WriteLine("i is int? {0}", i is int);
Console.WriteLine("i is long? {0}", i is long);

if (i is object) {
o = i;
Console.WriteLine("o의 Base Type은 " + o.GetType().BaseType);
}
}
}

 

---------------------------------------------

모든 Object(객체)들이 가지는 메소드

---------------------------------------------

객체 지향 프로그래밍을 하는것은 객체를 많이 다른다는 이야기 입니다. 이번에는 참고로 모든 객체들이 가지고 있는 기본적인 메소드가 어떤것이 있는지 필요한것만 보도록 하겠습니다. 닷넷에서는 System.Object가 모든 객체의 최상위 클래스 입니다. (물론 자바에선 java.lang.Object 입니다.)

메소드명 설명
bool Equals() 같은 객체인지 비교, 동일한 메모리 공간을 차지해야...
int GetHashCode() 해쉬값을 얻음
Type GetType() Type 에 관한 정보(형식 정보)를 돌려 줍니다.
string ToString() 객체를 대표하는 문자열 반환, 일반적으로 문자열로 변환한다고 보면 됩니다.

 

 

출처 :  http://cafe.naver.com/itclean.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=947


2008. 10. 3. 16:10

개설 후 첫글


드디어~나도 티스토리 입성..

맨날 여기저기 블로그로 전전긍긍하다가 이제 자리 좀 잡을려 한다.ㅎㅎ

일단 스프링 노트글을 여기로 좀 옮기고.~~

나중에 네어버 블러그도 옮길 예정이다..

졸업하기전에 구축을 해놔야 나중에 편할 듯..ㅎㅎㅎ

싸이 대용으로도 쓸 생각..ㅋㄷㅋㄷ