C# 용어 공부

CLR via C# 타입의 기초(1)

프로핌 2024. 2. 28. 00:45

 

모든 타입들은 궁극적으로 System.Object 타입으로부터 파생되는 것으로 하고 있다.

 

ex)

// 암시적으로 System.Object 타입으로부터 파생됨
class Employee{
....}


// 명시적으로 System.Object 타입으로부터 파생됨
class Employee : System.Object{
...}

 

 

모든 타입들이 Object 타입으로 파생되기 때문에 최소한 공통 기능을 모든 타입을 동일하게 가진다는것을 전제로 이야기 할 수있다.

 

그래서 모든 타입들은 Object의 내장되있는 메서드들을 호출이 가능하다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    public sealed class Program
    {
        protected static Int32 a = 0;
        
        static void Main(string[] args)
        {
            //Public 인스턴스 메서드
            a.Equals(a);
            a.GetHashCode();
            a.ToString();
            a.GetType();

            //Protected 인스턴스 메서드
            //MenberwiseClone()
            //Finalize()       
        }
    }
}

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

CLR은 모든 객체들을 new 연산자에 의하여 만들드록 하고있다.

 

Employee e = new Employee("ConstructorParaml");

 

 

여기서 new 연산자가 하는 일들을 간단히 정리하면 다음과 같다.

 

1. System.Object 타입을 포함한 기본 타입들에서 모든 인스터스 필드들을 메모리에 할당하기 위한 바이트 수를 계산한다.

    힙상의 모든 객체에는 타입 객체 포인터, 동기화 블록 인덱스가 추가되며 CLR에 의해 객체를 관리하기 위하여 사용된다

    이 추가 멤버들을 위한 바이트는 객체의 실제 크기에 포함된다.

 

2. 할당에 필요한 바이트의 수만큼 관리되는 힙으로부터 객체를 위하여 메모리를 할당하며 처음 할당할 때에는 모든 바이

    트를 0으로 초기화 한다.

 

3. 객체의 타입 객체 포인터와 동기화 블록 인덱스 멤버를 초기화한다.

 

4. 클래스 타입의 인스턴스 생성자와 인수가 new 연산자에서 서술한 대로 전달된다.

    각각의 호출되는 생성자는 타입에 의하여 정의된 인스턴스 필드들을 초기화 해야한다.

 

 

C#은 new연산자는 있지만 그걸 대응하는 delete 연산자는 존재하지 않는데 그 이유는 가비지 컬렉터가 자동으로 메모리 관리를 해주기 때문

 

 

 

 

객체의 타입을 확인하고 반환하는 is as 타입 연산자가 있다.

 

is연산자는 객체가 null이면 타입을 점검할 방법이 없어 항상 거짓을 반환한다.

 

if (o is Employee){
	Employee e = (Employee) o;
    // 이 조건문 안에서 e변수를 사용한다

 

 

 여기서 o 오브젝트는 Employee 호환이 되는지 검사를 한다음에 CLR이 o객체가 Employee 타입으로 캐스팅하면서 검사를 수행한다.

 

CLR의 타입 검사는 보안을 강화하지만 성능에 관한 일정한 비용이 발생하는데 비용이 발생하는 이유는 CLR이 변수 o에 들어있는 객체의 타입을 파악하기위해 상속 관계를 따져가면서 모든 타입들을 검사하기 때문이다.

 

그래서 C#은 이러한 작업을 단순화 하고 성능을 개선할 수 있도록 as 연산자를 제공한다.

 

Employee e = o as Employee;
if (e != null){
 // 이 조건문 안에서 e 변수를 사용한다.
 }

 

is문은 타입을 검사하고 그 객체를 참조하기 위해서 모든타입을 2번 검사했지만 as는 호환이 가능하면 유효한 참조를 캐스팅하여 반환하고 그렇지 않으면 null로 반환해 if문은 e가 호환이 되는지 안되는지 null로만 체크를 하면 되서 객체 타입을 좀 더 빠르게 검증할 수 있게 된다.