C# Object

선비Sunbei·2023년 1월 10일
0

C#

목록 보기
8/18
post-thumbnail
post-custom-banner

Object

C#은 모든 클래스들이 보이지않지만 상속하고 있는 C#의 기본 클래스 object가 존재한다.
object 클래스가 갖고있는 메서드는 다음과 같다.

메서드설명
Equals(Object)지정된 개체가 현재 개체와 같은지 확인한다.
Equals(Object,Object)지정한 개체 인스턴스가 동일한지 여부를 확인한다.
Finalize()가비지 컬렉션이 회수하기 이전에 개체가 리소스를 해제하고 다른 정리 작업을 수행할 수 있게 한다.
GetHashCode()기본 해시 함수로 해시 값을 반환한다.
GetType()현재 인스턴스의 Type을 가져옵니다.
MemberwiseClone()현재 Object의 단순 복사본을 만듭니다.
ReferenceEquals(Object,Object)지정한 Object 인스턴스가 동일한지 여부를 확인합니다.
ToString()현재 개체를 나타내는 문자열을 반환합니다.

Equals()와 ReferenceEquals()

Equals와 ReferenceEquals는 모두 같은 것인지 확인하지만, ReferenceEquals는 참조 주소가 같은지 즉, 같은 인스턴스인지 확인하는 것이고, Equals는 값이 같다는 것을 의미한다.
또 비슷한 것으로 == 연산자가 있을 것이다. 이 또한 클래스끼리 비교 시 ReferenceEquals 비교하듯이 비교한다. 이에반해 equals는 다음과 같이 재정의하여서 값이 같은지 비교할 것이다.

using System;

namespace Study13
{
    class Program
    {
        class Point
        {
            public int x, y;
            public Point(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
            public override bool Equals(object obj)
            {
                if (obj.GetType() != this.GetType())
                    return false;
                Point p = (Point)obj;
                return (this.x == p.x) && (this.y == p.y) ? true : false;
            }
        }

        static void Main(string[] args)
        {
            Point p1 = new Point(1, 2);
            Point p2 = new Point(1, 2);
            Point p3 = new Point(2, 2);

            if(p1.Equals(p2))
                Console.WriteLine("p1과 p2가 동일하다"); // o
            else
                Console.WriteLine("p1과 p2가 동일하지 않다.");
            
            if(p1.Equals(p3))
                Console.WriteLine("p1과 p3가 동일하다");
            else
                Console.WriteLine("p1과 p3가 동일하지 않다."); // o
            
            if(p2.Equals(p3))
                Console.WriteLine("p2와 p3가 동일하다");
            else
                Console.WriteLine("p2와 p3가 동일하지 않다."); // o
        }
    }
}

다음과 같이 Equals를 재정의하여 자신만의 Equals를 만들어 값을 충족하면 true를 반환하게끔 만들 수 있다.

GetType()

위 예제 코드에서 Object가 같은 타입인지 확인하기 위해서 Object 메서드의 GetType()을 썼다.
이에 대한 설명은 다음과 같은 코드를 보면 알 수 있다.

using System;

namespace Study14
{
    class Program
    {

        class Parent { }
        class Child : Parent { }

        static void Check(Parent p, string name)
        {
            if(p.GetType() == typeof(Child))
                Console.WriteLine($"{name}는 Child클래스입니다.");
            else
                Console.WriteLine($"{name}는 Child클래스가 아닙니다.");
            
            if(p.GetType() == typeof(Parent))
                Console.WriteLine($"{name}는 Parent클래스입니다.");
            else
                Console.WriteLine($"{name}는 Parent클래스가 아닙니다.");

            if(p is Parent)
                Console.WriteLine($"{name}는 Parent클래스를 포함합니다.");
            else
                Console.WriteLine($"{name}는 Parent클래스를 포함하지 않습니다.");

            if(p is Child)
                Console.WriteLine($"{name}는 Child클래스를 포함합니다.");
            else
                Console.WriteLine($"{name}는 Child클래스를 포함하지 않습니다.");

        }

        static void Main(string[] args)
        {
            Parent p = new Parent();
            Parent c = new Child();
            Check(p, "p");
            Check(c, "c");
            /*
             *  p는 Child클래스가 아닙니다.
                p는 Parent클래스입니다.
                p는 Parent클래스를 포함합니다.
                p는 Child클래스를 포함하지 않습니다.
                c는 Child클래스입니다.
                c는 Parent클래스가 아닙니다.
                c는 Parent클래스를 포함합니다.
                c는 Child클래스를 포함합니다.
             */
        }
    }
}

보다시피 is 키워드는 본인이 해당 클래스의 내용을 포함하고 있으면 true를 반환하는 반면에 GetType()은 어떻게 캐스팅되어있든 간에 해당 클래스가 어떤 클래스인지 확실하게 파악하는데 용의하다.

ToString()

using System;

namespace Study15
{
    class Program
    {
        class Point
        {
            private int x,y;
            public Point(int x, int y)
            {this.x = x;
             this.y = y;}
            public override string ToString()
            {
                return $"x : {x}, y : {y}";
            }
        }
        static void Main(string[] args)
        {
            Point p = new Point(2, 3);
            Console.WriteLine($"{p.ToString()}");
            // x : 2, y : 3
        }
    }
}

다음과 같이 클래스의 원하는 값들을 이용하여 해당 클래스 정보를 string형태로 꺼낼 수 있다.

GetHashCode()

수정 예정

MemberwiseClone()

해당 코드는 ShallowCopy이다.
MemberwiseClone()를 사용할 시 내부적으로 new를 통해 객체를 만든 후에 내부적인 변수들을 MemberwiseClone()를 호출한 객체와 동일하게 설정한다.
그런데 객체들을 저장하는 방식은 reference방식이기 때문에 ShallowCopy가 되는 것이다.
따라서 DeepCopy로 만드려면 MemberwiseClone을 한 후, 변수들을 new로 새로 생성한 후 호출한 객체의 값들을 복사해야 한다.

Finalize()

C#의 경우 C/C++처럼 new를 한 후에, delete로 메모리를 관리하지 않아도 CLR의 Garbage Collector가 오랫동안 사용하지 않으면 객체를 자동으로 소멸해주기 때문에 new를 사용한 후에 삭제에 대한 신경을 쓰지 않아도 된다.
Finalize() 함수는 객체가 Garbage Collector에 의해 소멸되는 시점(소멸자 이후)에 호출된다. (암시적으로)

즉, GC가 어제 호출될지 모르기 때문에 우리는 용량이 큰 리소스를 직접 해제할 수 있는 방법을 만들어놔야 한다.(명시적으로)

수정 예정

boxing과 unboxing

C#은 모든 클래스가 object를 상속하고 있다. 이는 다형성 측면에서 유용하다.
이에 대해서 C#에서는 boxing과 unboxing이라는 용어로 object의 캐스팅 상태를 말한다.

using System;

namespace Study16
{
    class Program
    {
        class ClassName1 { 
            public void Print()
            {
                Console.WriteLine("CN1 출력");
            }
        }
        class ClassName2
        {
            public void Print()
            {
                Console.WriteLine("CN2 출력");
            }
        }

        static void PrintCN(Object obj)
        {
            if(obj is ClassName1)
            {
                ClassName1 cn1 = (ClassName1)obj; // unboxing
                cn1.Print();
            } 
            else if (obj is ClassName2)
            {
                ClassName2 cn2 = (ClassName2)obj; // unboxing
                cn2.Print();
            }
            else
            {
                Console.WriteLine("Not-CN");
            }
        }

        static void Main(string[] args)
        {
            ClassName1 cn = new ClassName1();

            Object obj = cn; // boxing

            PrintCN(obj);
            // CN1 출력
        }
    }
}

boxing 상태로 관리하게 될 경우 하나의 object 배열을 이용해서 관리할 수 있다는 장점이 있지만 강제 형변환같은 것에 비용이 발생한다는 단점이 있다.

post-custom-banner

0개의 댓글