본문 바로가기
컴퓨터/C#

[C#] Object 타입

by 아기상어  2020. 6. 2.

System.Object

 

C#에 존재하는 모든 클래스들은 상속받는다고 쓰지 않아도 Object 타입에 상속을 받고 있다.

 

모든 타입의 조상. 모든 값타입(int, double 등등) 참조 형식(enum, struct) 등이 Object 클래스를 상속 받는다.

 

이 Object 타입은 4개의 메서드를 가지고 있다. ToString, GetType, Equals, GetHashCode 가 4가지 메서드이다.

 

 

예제) C가 B를 상속받고 B가 A를 상속받을때 각각 객체 참조변수가 가리킬 수 있는 객체의 개수

    class A
    { }

    class B : A
    { }

    class C : B
    { }
    
    class Program
    {
        static void Main(string[] args)
        {
            A aObj = new A();
            B bObj = new B();
            C cObj = new C();
            
            A aRef;
            B bRef;
            C cRef;
            
            //퀴즈 1 : aRef가 가리킬 수 있는 객체는 모두 몇 개인가? 3개
            
            aRef = aObj;
            aRef = bObj;
            aRef = cObj;
            
            //퀴즈 2 : bRef가 가리킬 수 있는 객체는 모두 몇 개인가? 2개
            
            bRef = bObj;
            bRef = cObj;
            
            //퀴즈 3 : cRef가 가리킬 수 있는 객체는 모두 몇 개인가? 1개
            
            cRef = cObj;
            
            //오브젝트 클래스는 다 가리킬 수 있다.	3개를 다 가리킬수있다.
            Object oRef;
            oRef = aObj;
            oRef = bObj;
            oRef = cObj;

        }
    }

 

A는 B와C를 자녀 클래스로 두고 있어서 ABC 객체 모두를 가리킬수 있다.

 

B는 C를 자녀클래스로 두고 있어서 BC만 가리킬 수 있고

 

C는 자기 자신만 가리킬수 있다.

 

Object는 모든 클래스의 부모클래스 이므로 ABC를 가리킬 수 있다.

 

ToString

해당 인스턴스가 속한 클래스의 전체 이름을 반환한다.

값타입에서 사용하면 해당타입이 담고있는 값을 반환한다.

 

예제) 위 소스의 aObj, bObj, cObj ToString() 해보기

            Console.WriteLine(cObj.ToString());
            Console.WriteLine(aObj.ToString());
            Console.WriteLine(bObj.ToString());

 

 

namespace이름.클래스이름

이 출력되었다. Program 클래스 안에 있었다면 

_20200602_001.Program.C

_20200602_001.Program.A

_20200602_001.Program.B

가 출력되었을 것이다

 

예제) 값타입에 ToString() 써보기

            int n = 500;
            double d = 3.1415926535897932384626;
            string txt = "Hello: ";
            Console.WriteLine(txt + n.ToString());
            Console.WriteLine(txt + d.ToString());

            txt = d.ToString();

            Console.WriteLine(txt);

 

 

값타입에 쓰면 해당타입의 값을 반환한다.

 

 

 

GetType

클래스로 타입을 정의하면 (Type type = 클래스명.GetType())

해당 class의 타입정보를 가지고 있는 System.Type의 인스턴스를 보유하게 되고 이걸 GetType 메서드로 가져올 수 있음.

값타입에서 선언되었다면 클래스에 대해 타입의 전체 이름을 반환한다.

 

예제) GetType으로 클래스의 인스턴스 가져오기

            Type type = cObj.GetType(); //  GetType의 반환객체는 Type이다.


            Console.WriteLine(type.FullName);
            Console.WriteLine(type.IsClass);
            Console.WriteLine(type.IsArray);

위에서 썻던 C클래스에 GetType()을 한것이다.

 

FullName은 ToString 같이 namespace와 클래스명이 출력되었고

IsClass는 GetType으로 반환된 객체 type이 클래스이냐? 참이면 True, 거짓이면 False를 반환한다.

IsArray도 마찬가지로 type이 Array이면 참 True, 거짓이면 False를 반환한다.

 

예제) int와 string 변수에 GetType() 써보기

            int n = 5;
            int n2 = 5;
            string txt = "text";

            Type intType = n.GetType();

            Console.WriteLine(intType.FullName);
            Console.WriteLine(txt.GetType().FullName);

 

 

 

Equals

Equals도 값 형식에 썼는지 참조 형식에 썼는지에 따라 다르다.

참조형식.Equals(참조형식) 에 사용할 경우 할당된 메모리 위치를 가리키는 식별자의 값이 같은지 비교한다.

값형식.Equals(값형식)에 사용할 경우 변수가 가리키는 값 자체를 반환하므로 결괏값끼리 같은지 비교한다.

 

만약 Book 클래스로 new를 이용해 b1, b2 객체를 생성했다고 생각해보자.

 

 

예제) Book클래스로 b1 b2 객체를 생성해서 Equals() 해보기

    class Book
    {
        decimal _isbn;
        public Book(Decimal isbn)
        {
            _isbn = isbn;
        }
    }
            Book b1 = new Book(9788998139018);
            Book b2 = new Book(9788998139018);
            Book b3 = b1;
            Console.WriteLine("Book클래스 b1과 b3객체는 같은가 : " + b1.Equals(b3));
            //  데이터주소를 가리키는 스택변수의 값을 서로 비교 False 반환

 

False가 나올것이다. new Book으로 생성된 힙메모리의 위치가 다르기 때문이다.

 

예제) 값타입으로 Equals() 해보기

            string aString1 = "test";
            string aString2 = "test";
            string aString3 = aString1;     //  1,2,3은 같은곳에 있는 "test"를 가리킨다.

            if (aString1.Equals(aString2))
            {
                Console.WriteLine("스트링1과 2는 참");
            }
            if (aString1.Equals(aString3))
            {
                Console.WriteLine("스트링1과 3은 참");
            }
            if (aString2.Equals(aString3))
            {
                Console.WriteLine("스트링2와 3은 참");
            }

 

 

모두 True가 나오게 된다. aString1,2,3가 소유하는 값을 대상으로 비교한다.

 

GetHashCode

특정 인스턴스를 고유하게 식별할 수있는 4바이트 int값을 반환한다.

 

Equals의 반환값이 True인 객체라면 서로 같음을 의미하고 그 객체들을 식별하는 고윳값 또한 같다.

 

int값을 반환하므로 int값을 넘어서는 값을 GetHashCode 했을 경우 

 

다른 값인데도 같은 해시코드를 생성하는 해시 충돌(Hash Collision)이 발생할 수 있다.

 

이럴경우 다시한번 Equals()를 호출해서 동일한지 판단할 수 있는 기회가 생긴다.

 

예제)

            Book b1 = new Book(9788998139018);
            Book b2 = new Book(9788998139018);

            short n1 = 256;
            short n2 = 32750;
            short n3 = 256;

            Console.WriteLine(n1.GetHashCode());
            Console.WriteLine(n2.GetHashCode());
            Console.WriteLine(n3.GetHashCode());

            Console.WriteLine("북클래스 b1과 b2의 해쉬코드");
            Console.WriteLine(b1.GetHashCode());
            Console.WriteLine(b2.GetHashCode());