* 정의
C#의 모든 타입은 object의 상속을 받고 있다. 기본 데이터 타입, 복합 데이터 타입 그리고 그 타입이 참조 타입이든 값 타입이든 예외 없이 모두 object이다. ildasm 툴로 확인하면 모두 object(System.Object)를 상속받고 있다는 것을 볼 수 있다. 간단히 계층 구조에서 루트이다. 심지어 값 타입을 나타내는 System.ValueType 조차 object를 상속받고 있다.
object는 C#의 모든 타입을 다룰 수 있으며 기본적인 기능과 리플렉션관련 기능을 제공한다.
< 간단한 계층 구조 다이어그램 >

< ildasm으로 봤을 때 System.Object를 상속받는다. >

< 값 타입을 나타내는 System.ValueType에서 object의 가상함수를 오버라이딩하고 있다. >

* 동작 방식
- object의 가상 함수
암시적으로 object를 상속 받고 있기 때문에 사용자에게 특정 기능을 구현 코드를 강요하지는 않지만 다음과 같은 가상 함수를 오버라이딩하여 사용할 수 있다.
다음과 같은 종류를 가지고 있다.
- Equals : 객체간 비교를 지원하기 위해 오버라이딩한다.
- GetHashCode : 객체를 구분하기 위한 객체에 해당하는 값(숫자)를 생성하기 위해 오버라이딩한다. 이를 기반으로 해시 테이블의 사용을 지원한다.
- ToString : 클래스 인스턴스를 설명하는 문자열을 만들기 위해 오버라이딩한다.
- Finalize : 객체를 가비지 컬렉터가 수거하기 전에 리소스나 정리 관련 코드를 실행하기 위해 오버라이딩한다.
위에서 3가지 함수의 시그니처는 다음과 같다. 필요에 따라 구현하면 된다.
- public virtual bool Equals(Object? obj);
- public virtual bool Equals(Object? obj);
- public virtual string? ToString();
Finalize는 소멸자를 통해 선언할 수 있다. 자식 클래스 소멸자 > 부모 클래스의 소멸자 호출이 보장되도록 코드가 생성되기 때문에 C++처럼 가상 소멸자를 신경쓸 필요 없다.

- object 사용 시 주의 사항 : Boxing Unboxing
예를 들어 C#의 Collection과 같은 여러 타입에 대해 처리할 수 있는 컨테이너 형 클래스를 설계한다고 가정해보자.
모든 타입은 object 타입이므로 object를 내부 객체로 가지도록 만들 수 있다. 하지만 이렇게 설계하게 되면 박싱과 언박싱 과정이 발생하게 된다.
박싱 과정을 방지하기 위해 다음과 같은 방법을 고려해볼 수 있다.
- object타입을 받는 일반적인 메소드를 만들고 특정 타입에 대한 오버로딩된 메소드를 만든다. 이렇게 오버로딩된 메소드들에서는 박싱 과정이 발생하지 않는다. 하지만 지원하지 않는 타입이 들어왔을 때 박싱 과정을 거치게 된다.
- 제네릭(generic)을 사용하도록 디자인한다. CLR은 클래스 객체를 만들고 제니릭 타입 인수를 지정할 때 닫힌 제네릭 형식(closed generic type, 타입을 확정한다는 뜻인 것 같다.)을 만든다. 여기서 메소드는 타입 별로 존재하고 매개변수를 박싱하지 않고 호출될 수 있다.
'C#' 카테고리의 다른 글
| [C#] var (0) | 2022.06.28 |
|---|---|
| [C#] 박싱과 언박싱(Boxing and Unboxing) (0) | 2022.06.28 |
| [C#] string vs StringBuilder (0) | 2022.06.28 |
| [C#] Nullable 타입 (0) | 2022.06.28 |
| [C#] 값 타입과 참조 타입(Value type, Reference type) (0) | 2022.06.28 |