참조 타입(Reference Type)






.NET 의 타입은 크게 값 타입(Value Types) 과 참조 타입(Reference Types) 으로 나뉜다. 값 타입은 Buit-In Value Type (int, float, double.. 등 8개) 과 User-Defined value Types (구조체), Enumerations (열거 값) 이며 이들을 제외한 타입은 참조 타입이 된다.







값 타입을 비교할 때는 == 와 != 연산자를 사용한다. ==, != 연산자가 오버로딩 되어 있기 대문이다.
원칙적으로 참조 타입을 ==, != 연산자로 비교한다면 똑같은 값을 가리켜도 참조변수 자체는 다른 주소값을 가지기 때문에 비교값이 틀리다고 결과를 리턴한다. 하지만 몇몇 참조 타입은 ==, != 연산자가 오버로딩 되어 있어서 값을 비교할 때 ==, != 연산자를 사용할 수 있다. 중요한건 모든 참조 타입이 ==, != 연산자를 오버로딩 한 것은 아니므로 사용할 때 주의를 요한다. 최근 Java 에서도 ==, != 연산자 오버로딩을 허용하는 분위기 이다.







값 타입은 메모리가 Stack 에 할당된다. 참조 타입은 메모리가 Heap에 할당 되고, Heap에 할당된 메모리를 가리키는 참조 변수는 Stack에 할당 된다. Heap은 사용자가 관리하는 대상이 아니라 CLR이 관리한다. 참조 변수에 null 값을 대입하는 것은 해당 메모리의 해제가 아니라 Heap에 생성된 메모리와의 연결을 끊는 것이다. 연결이 끊어진 메모리는 그 메모리를 더이상 참조하는 참조 변수가 없다면 가비지 컬렉터가 메모리를 해제 한다.








String 타입은 참조 타입이다. 특이 하게 String 타입은 Immutable (수정 불가능) 하다. 주어진 String 값을 변경하면 새로운 문자열을 할당하여 그 메모리 주소를 넘겨 받는 식으로 되어 있기 때문에 하나의 String 객체로 많은 문자열 수정을 가하는 로직은 많은 오버헤드가 걸린다. 대안으로 StringBuilder 클래스를 사용한다.







Object





Object 클래스는 .NET 클래스의 최상위 클래스로서 모든 .NET 클래스는 Object를 부모 클래스(Based class)로 가진다. Object는 위와 같이 ToString, Equals, GetType, Finalize 메소드를 갖는다. 따라서 .NET의 모든 클래스는 4가지 메소드를 기본적으로 가지고 있다. GetType 메소드는 Reflection 기술의 핵심 메소드 이다.


※ GetType 메소드를 이용한 Run-time 타입 정보 얻기



위와 같이 Form 으로 부터 상속받은 Form1 은 자기 자신을 나타내는 this 다음에 . 을 찍으면 자신이 가지고 있는 것을 출력 시켜 준다. 인텔리센스 라고 하는데 이 기술 역시 Reflection 기술을 이용해 알 수 있는 것이다.

Form 이 가지고 있는 것을 Run-time 에 GetType 메소드를 사용하여 정보를 ListBox 에 뿌려 보았다.

private void button1_Click(object sender, EventArgs e)
{
    Type t =  this.GetType();
    MemberInfo[] m = t.GetMembers();            

    foreach(MemberInfo mi in m)
    {
        listBox1.Items.Add(mi.MemberType.ToString() + " : " + mi.Name);
     }
}












namespace !! C++ 의 네임스페이스와 비슷한 용도 이다.
namespace 란 클래스의 유일성을 보장하는 논리적인 이름의 공간이다.










Type Converting
값타입 → 값타입, 참조 타입 → 참조 타입  즉, 같은 타입 간에는 Casting 연산자(괄호)를 사용하여 타입 변환을 할 수 있다. 하지만 값타입 → 참조 타입, 참조 타입 → 값타입 으로의 형변환은 특정 메소드를 사용한다.
ex) int.Parse()  Convert 클래스

int i, j;

if (!int.TryParse(textBox1.Text, out i))
{
    MessageBox.Show("숫자 입력하라고!!");
    return;
}

i = int.Parse(textBox1.Text);
j = Convert.ToInt32(textBox2.Text);            

// int.TryParse
// 해당 값이 int 값인지 확인
int num = i + j;
MessageBox.Show(num.ToString());
// MessageBox.Show(Convert.ToString(num));



※ 값 타입의 묵시적인 형변환에 다른 checked 사용

값 타입간의 형변환 중 크기가 작은 타입이 큰 타입으로 형변환 될 때는 문제가 없지만, 크기가 큰 타입이 크기가 작은 타입으로 형변환 될 때 오버플로가 발생되며, 아무 경고 없이 묵시적으로 오류 값을 저장하게 된다. 하지만 이것은 문제의 소지가 있으므로 오버플로가 발생 되었을 때 예외를 던져주는 checked 를 사용해서 코딩해 주어야 한다. 이때, checked 를 사용한다고 해서 문제를 해결해 주는 것은 아니고 예외만 던져 주는 것 이므로 던져주는 예외를 처리 하는 코드를 직접 작성해 주어야 한다.


try
{
    checked
    {
        long k = long.MaxValue;
        MessageBox.Show(k.ToString());

        // over flow 발생
        // 묵시적으로 오버플로 무시됨.
        // checked 를 이용하여 예외 발생 시키기
        // 예외를 처리해 주자!!!!
        int i = (int)k;
        MessageBox.Show(i.ToString());
    }
}
catch (Exception ex )
{
    MessageBox.Show(ex.Message);
}








※ 다형성의 구현
1. virtual     : 선택 사항
2. abstract  : must override
3. interface : all must override


다형성!!  메소드에만 존재하는 개념

다형성의 원리는 "부모는 자식을 참조할 수 있다."

객체지향적으로 작성된 것을 어떻게 잘 사용할 것인가!!
Posted by six605
,