[C#] C#은 모든 자료형이 객체일까?

❓ C#은 모든 자료형이 객체일까?

한 가지 의문으로부터 본 포스팅은 시작한다.


오늘 문득 생각에 잠겨 C#은 진짜 모든 자료형을 객체로 취급할까?라는 의문을 품고 직접 검증에 나섰다.

결론부터 말하면 모든 자료형을 객체로 취급한다는 말은 엄연히 틀리며 해석하기에 두 가지 답을 제시할 수 있다.

✍️ int는 객체인가?

C#에서 모든 자료형은 객체인가를 알기 전에 int는 객체인가 대한 정답을 내리면 정답에 한걸음 다가갈 수 있지 않을까?

기본적으로 C#에선 class와 String(string)은 Reference-type이며 struct와 enum은 Value-type이다.
여기서 한 가지 중요한 사실은 int와 같은 원시 타입은 구조체로 구현했단 점이다.

https://keumjae.tistory.com/177


int는 구조체로 구현했다. 굉장히 많은 의미를 담고 있는 문장이다. 왜냐하면 많은 사람들이 C#의 구조체는 상속받을 수 없으며 상속할 수도 없는 자료형으로 알고 있기 때문이다. 그럼에도 불구하고 int는 System.ValueType이란 추상 클래스를 상속받고 있다.
코드를 작성해 보면 int는 최상위 클래스 object가 제공하는 ToString 메서드를 사용 가능한 점을 고려했을 때 int(구조체)가 System.ValueType을 상속받는 것은 자명해 보인다.


다만 여전히 의구심이 든다. 정말 구조체가 상속을 받을 수 있는 거야?
여기에 저명한 C# 개발자 Eric Lippert가 stackoverflow에 답변을 남겼다.

간략하게 정리하자면 구조체가 클래스를 상속받는 것은 가능하며 모든 구조체는 System.Object로부터 파생된 System.ValueType 클래스를 암시적으로 상속받고 있다. 따라서 사용자 정의 구조체를 비롯한 모든 구조체는 임의의 클래스로부터 상속받는것은 명백히 불가능하다.

추가 자료

C# language spec, 4.1.1:

4.1.1 The System.ValueType type

All value types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object. It is not possible for any type to derive from a value type, and value types are thus implicitly sealed (§10.1.1.2).


Then, later (4.1.3) struct is explicitly defined to be a value type:

4.1.3 Struct types

A struct type is a value type that can declare constants, fields, methods, properties, indexers, operators, instance constructors, static constructors, and nested types.

 

🤔 그렇다면 모든것들이 객체일까?

다시 원래 궁금증으로 돌아오면, 그렇다면 C#에서 모든 것은 객체일까?
여기에 대한 두 가지 해석이 존재한다.
해석이 갈리는 이유는 C#에서 객체라는 단어가 다소 모호한데, .NET framework에서 정의한 System.Object의 별칭이 객체(object)이며 또한 동적으로 생성된 클래스의 인스턴스도 객체라고 부르기 때문이다.

첫 째로 상속적인 측면에서 모든 것을 객체라고 묻는다면 "거의 모든 것들"은 객체이다.
모든 Value-type과 클래스, 배열, 델리게이트는 System.Object를 상속받음으로써 객체이나 인터페이스 타입과 포인터는 System.Object을 상속받지 않아 객체라고 말할 순 없다.
이처럼 거의 모든 타입이 System.Object를 상속받아 객체라고말 할 수 있지만 여전히 레퍼런스 타입과 벨류타입이 다뤄지는 혹은 동작하는 방식이 매우 다르기에 이는 두번째 해석으로 이어진다.

두 번째로 Reference-type과 Value-type의 관점으로 본다면 명백히 모든 것은 객체가 아니다.
Value-type이 System.Object를 상속받으나 그것들이 Reference-type(객체)과 전혀 다르게 취급된다.
예를 들면 Value-type은 데이터를 자체적으로 할당된 메모리에 저장하는 반면 Reference-type은 실제 데이터가 할당된 주소 공간을 가리킨다. 그뿐만 아니라 다른 변수에 값을 대입하는 과정도 이 둘은 너무나 다른 결과를 야기한다.
즉, Value-typeReference-type은 전혀 다르게 다뤄지며 Value-type을 명시적으로 박싱(Boxing)해야만 Reference-type으로 변환된다.

int num = 23; // 23이 num에 할당됨 
Object obj = num; // 박싱(Boxing)

https://www.partech.nl/nl/publicaties/2021/07/what-is-boxing-and-unboxing-in-c-sharp#

 

🍊 결론

C#은 모든 자료형을 객체로 취급하지 않는다.

거의 모든 자료형은 System.Object를 상속받는다는 표현이 적합하다.