IT공부/IT서적

[헤드퍼스트 C#] Chapter 4. 참조 이해하기

shine94 2025. 6. 16. 07:40

* 해당 글은 시작하세요! 헤드퍼스트 C# 도서를 읽고 정리한 글입니다.

   https://product.kyobobook.co.kr/detail/S000211338172

 

헤드 퍼스트 C# | 앤드류 스텔만 - 교보문고

헤드 퍼스트 C# | 상상을 초월하는 객체지향 C# 학습법 직관적인 설명과 다채로운 구성으로 생생하게 체험하는 C# 프로그래밍재치 넘치는 설명과 틀에 박히지 않은 구성으로 복잡한 개념도 쉽게

product.kyobobook.co.kr

   https://github.com/head-first-csharp/fourth-edition

 

GitHub - head-first-csharp/fourth-edition: Code and graphics for the projects in the 4th edition of Head First C#

Code and graphics for the projects in the 4th edition of Head First C# - head-first-csharp/fourth-edition

github.com

 

 

 

 

* 다양한 타입의 데이터가 존재하는 캐릭터 시트

   캐릭터에 대한 각종 정보를 저장하는 클래스를 만들기 위해서는 필드의 타입을 적절히 선택해야 한다

   이 과정은 캐릭터 클래스를 설계할 때, 매우 중요한 과정이다

 

   데이터의 종류를 결정하는 변수 타입

   어떤 데이터인지에 따른 변수의 타입을 알맞게 선택해야 한다

   대표적으로 정수, 실수, 불리언, 문자열이 있다

 

   .NET과 메모리 관계

   결국 C#에서 쓰는 키워드들은 컴파일러가 .NET의 타입으로 매핑해준다

   즉, int 같은 키워드는 내부적으로 System.Int32로 변환되어 처리한다

   (유니티는 Mono나 IL2CPP 같은 Unity 전용 런타임 플렛폼을 따로 사용)

 

 

   .NET을 쓴다는 건(유니티도 동일) OS나 CPU 아키텍처에 상관없이 자료형 범위를 일관되게 쓸 수 있다는 의미다

 

   이걸 효과적으로 증명하기 위해 C/C++와 비교해보면,

   C/C++은 운영체제와 CPU 아키텍처에 따라 자료형 크기가 달라질 수 있다

 

   왜 달라지는지 예를 들면, C/C++는 int, long 같은 타입 크기를 고정하지 않고 OS와 CPU에 맡긴다

   CPU가 32비트인지 64비트인지에 따라 레지스터 크기도 다르고,

   OS는 커널 구조체와 시스템콜 규약에 맞게 자료형 크기를맞춘다

   그래서 같은 C/C++ 코드라도 OS나 CPU에 따라 자료형 크기가 달라진다

 

원인 설명
표준의 유연성 C/C++ 표준은 int, long의 크기를 고정하지 않음
최소 크기만 정의
CPU 아키텍처 CPU가 32비트냐 64비트냐에 따라 register 폭이 다르므로, 최적 성능을 위해 int 크기를 맞추기도 함
운영체제 ABI 시스템콜, 커널 구조체와 호환을 위해 OS별로 타입 크기를 다르게 둔다
시스템 프로그래밍 low-level 코드는 시스템콜 직접 호출 시 타입 크기가 맞아야 한다
OS마다 syscall 번호와 파라미터 구조가 다르다

 

OS int long
Windows 32비트 32비트 32비트
Windows 64비트 32비트 32비트
Linux 32비트 32비트 32비트
Linux 64비트 (LP64) 32비트 64비트

 

   (1) 정수를 저장할 수 있는 여러 C# 타입들

https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/builtin-types/integral-numeric-types

 

정수 숫자 형식

각 정수 숫자 형식에 대한 범위, 스토리지 크기 및 용도에 대해 알아봅니다.

learn.microsoft.com

 

   (2) 정말 큰 수와 작은 수를 저장하는 타입

https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types

 

부동 소수점 숫자 형식 - C# reference

기본 제공 C# 부동 소수점 형식인 float, double 및 decimal에 대해 알아보기

learn.microsoft.com

 

   (3) 문자열(string)

   기본 타입이지만 참조형이다

 

* Convert 클래스

   데이터 타입 간의 값을 서로 변환할 수 있다

int number = Convert.ToInt32("123");
bool flag = Convert.ToBoolean("true");

 

(+) Convert 클래스 외에도 데이터 타입 간 값을 변환할 수 있는 메서드들이 있으므로 정리하면 아래와 같다

클래스명 null 예외 발생 여부 설명
Convert null-safe (0, false 반환) 형식이 틀리면 예외 null-safe이지만 일부 상황은 예외
Parse null이면
ArgumentNullException
형식 틀리면
FormatException
무조건 올바른 형식만 허용
TryParse null이면 false 반환 형식 틀리면 false 반환 절대 예외 없음
실패시 false

 

* 모든 객체가 해당객체를 문자열로 변환하는 ToString() 메서드를 가지고 있다

 

* object 타입

   모든 타입의 최상위 부모 타입이다

   (즉, 모든 클래스, 구조체, 열거형, 델리게이트 등은 모두 System.Object를 상속 받음)

   모든 타입이 object를 상속받기 때문에, 모든 객체는 ToString(), Equals(), GetHashCode() 같은 메서드를 기본으로 가진다

 

* 헷갈릴만한 용어 정리

   시스템콜

   운영체제가 제공하는 기능을 프로그램이 직접 호출할 수 있도록 만든 특별한 함수

 

   시스템 프로그래밍

   시스템콜, 커널 구조, OS API 등 운영체제의 저수준 핵심을 다룬다

   ㄴ 시스템콜(예: TV 신호 전송 프로토콜)

       커널 함수

   ㄴ 커널구조(예: TV 내부 회로 설계도)

       운영체제가 CPU, 메모리, 파일시스템, 드라이버, 시스템콜 등을

       어떻게 모듈화해서 연결해두었는지 설명하는 OS의 핵심 설계도다

   ㄴ OS API(예: 편의용 리모컨, 버튼만 누르면 쉽게 동작)

       언어/라이브러리에서 제공하는 시스템콜 래퍼

 

   cmd.exe의 쉘 명령어는 OS API를 호출해서 수행한다

   시스템 콜을 직접적으로 호출하지 않는다

 

https://shine94.tistory.com/403

 

[운영체제] 시스템 콜(System Call)

* 시스템 콜(System Call)   사용자 모드에서 운영체제(OS)의 커널의 기능을 요청할 수 있도록 제공되는 인터페이스   (예) 운영체제(OS)의 API          ㄴ 유저는 시스템 콜을 사용하여 OS에 요청을

shine94.tistory.com

 

   기본 자료형(= 원시타입, primitive type)

   언어가 기본으로 제공하는 타입으로 값타입이다

   C#(13개)

   bool, byte, short, int, long, ushort, sbyte, uint, ulong, char, float, double, decimal

   Java(8개)

   boolean, byte, short, int, long, char, float, double

 

   기본 제공 참조 타입

   C#은 자바와 달리 별칭을 제공한다

   C#

   string

   Java

   String

 

   namespace

   C#

   클래스를 논리적으로 묶어주는 이름공간

   물리적인 폴더 구조와 일치하지 않아도 됨

 

   package

   Java

   클래스를 논리적 + 물리적으로 묶어주는 이름공간

   물리적인 폴더 구조와 일치해야 함

 

   상수

   값을 바꿀 수 없는 고정된 변수

   컴파일시 메모리 할당

   ㄴ 리터럴(literal) : 이름 없는 상수

   ㄴ readyonly : 런타임 상수, 선언 시 초기화하거나 생성자에서 할당 가능

 

   열거형

   관련 상수를 그룹으로 묶는 타입

   상수와 같지만 용도가 달라 구분

   컴파일시 메모리 할당, 내부적으로는 숫자값

 

   static

   프로그램에서 하나만 존재

   컴파일 시 메모리에 올라감 → 인스턴스를 만들 수 없음, 변수로도 담을 수 없음

 

* 캐스팅된 값이 범위를 초과하면 모듈러 연산(%)되어 범위 내 값으로 wrap around 된다

   wrap around 은 직역하면 "둘러서 다시 돌아온다"

   즉, 값이 데이터 타입의 최대값을 넘어가면, 넘친 만큼 다시 최소값부터 이어서 계산된다는 뜻이다

   모든 언어가 wrap around 되지만, C/C++의 signed에서는 오버플로우가 될 수 있다

 

* 모든 타입이 캐스팅 되는 건 아니다

   기본 자료형(원시타입, primitive type)은 언어에서 기본 캐스팅 규칙을 제공한다

   C#

   클래스/구조체에 대해 암시적(implicit)/명시적(explicit) 형 변환 연산자 추가 정의 가능(연산자 오버로딩)

   Java

   연산자 오버로딩 및 형 변환 연산자 추가 정의 불가능

   필요한 경우 메서드를 만들어 직접 수동 변환해야 한다

class Meter
{
    public double Value;

    public Meter(double value)
    {
        Value = value;
    }

    // 사용자 정의 암시적 변환
    public static implicit operator Meter(double d) => new Meter(d);

    // 사용자 정의 명시적 변환
    public static explicit operator double(Meter m) => m.Value;
}

Meter m = 10.5;      // implicit: double -> Meter
double d = (double)m; // explicit: Meter -> double

 

C# 컴파일 과정
   소스코드 → 컴파일러 → IL 코드 → CLR(Common Language Runtime) → JIT(Just In Time) 컴파일러 → 기계어 실행

 

   C# 컴파일러는 소스코드를 중간 언어(IL)로 컴파일한다
   CLR이 IL 코드를 JIT 컴파일하여 CPU의 기계어로 변환한 뒤 실행한다

 

* C/C++은 비주얼 스튜디오 전용 컴파일러를 쓰는데, C#은 비주얼 스튜디오와 Rider 모두 같은 컴파일러를 쓴다

   C/C++

   비주얼 스튜디오 : MSVC 컴파일러

   macOS/Linux : 보통 GCC, Clang

   IDE에 따라 기본 연결된 컴파일러 다름

   C#

  .NET SDK 안에 Roslyn 컴파일러가 포함

   비주얼 스튜디오, 라이더, VS Code 전부 동일 Roslyn 사용

 

* 화폐 같은 금전 데이터는 float, double 타입을 사용하면 안된다

   부동소수점 연산은 근사값 사용하여 누적 오차가 발생할 수 있다

 

https://shine94.tistory.com/456

 

[C#] .NET 9 decimal 구조체 톺아보기

* decimal 구조체의 최신 원본 코드(공식 레파짓토리)https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Decimal.cs?utm_source=chatgpt.com runtime/src/libraries/System.Private.CoreLib/src/System/Decimal

shine94.tistory.com

 

* 참조 변수

   메모리에 저장된 객체(인스턴스)의 주소를 저장하는 변수

 

   C#(힙 생성 가능)

   (1) Monster monster = new Monster();

        힙에 Monster 생성

        스택변수 monster에는 힙 객체 주소가 참조 형태로 들어 있음

 

   C++(스택, 힙 생성 가능)

   (1) Monster monster;

        스택에 Monster 생성

   (2) Monster* pMonster = new Monster();

        힙에 Monster 생성

        반환된 주소를 pMonster 포인터 변수에 저장

 

* 클래스 객체 힙 생성시 메모리 구조

 

참조되지 않은 객체는 가비지 컬렉션된다

   C#은 가비지 컬렉션(Garbage Collection, GC)으로 동적 메모리를 자동 관리한다

   더 이상 어떤 참조 변수에도 연결되지 않는 객체는 GC가 찾아서 제거한다

   제거된 메모리는 프로그램이 다시 쓸 수 있도록 자동 회수된다

 

https://shine94.tistory.com/459

 

[C#] .NET 가비지 컬렉션(GC, Garbage collection) 둘러보기

*참고한 공식 문서https://learn.microsoft.com/ko-kr/dotnet/standard/garbage-collection/fundamentals 가비지 컬렉션 기본 사항 - .NET가비지 수집기의 작동 원리와 최적 성능으로 구성하는 방법에 대해 알아봅니다.lear

shine94.tistory.com

 

* 다중 참조와 부작용

   하나의 객체를 여러 참조 변수가 가리킬 수 있으며, 이를 다중 참조라고 한다

   변수의 참조를 바꾸면, 이전 참조가 끊어지면서 해당 객체는 GC 대상이 될 수 있다

   참조 변경에 따라 의도치 않은 객체 제거와 메모리 회수가 발생할 수 있으므로 주의가 필요하다

 

* this 키워드

   현재 객체의 주소를 담고 있는 특별한 참조 변수

 

* 참조를 사용해 서로 대화하는 객체

   Elephant 클래스가 다른 Elephant  객체를 파라미터로 받아 메시지를 전달

 

string Name;

// 메시지 수신
public void HearMessage(string message, Elephant whoSaidIt)
{
    Console.WriteLine(Name + " hear a message");
    Console.WriteLine(whoSaidIt.Name + " hsaid this " + message);
}

// 메시지 송신
public void SpeakTo(Elephant whoToTalkTo, string message)
{
    whoToTalkTo.HearMessage(message, this);
}

 

* null

   참조가 가리키는 객체가 없다

 

* 배열

   같은 타입의 여러 값을 연속된 메모리 공간에 저장할 수 있는 자료구조

   값이나 참조를 저장할 수 있다

 

* 컬렉션 이니셜라이저(collection initializer)

   new 키워드와 배열 타입을 지정하여 배열을 초기화하면서,

   배열에 넣을 요소를 콤마로 구분해서 중괄호에 넣는 방식으로 배열 값을 지정할 수 있다

 

 

* .NET Random 클래스

   컴퓨터의 시간을 초깃값(seed)으로 사용하는 유사난수 생성기를 만든다

 

https://shine94.tistory.com/457

 

[C#] .NET 9 Random 클래스 살펴보기

* Random 공식 레포지토리https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Random.cs runtime/src/libraries/System.Private.CoreLib/src/System/Random.cs at main · dotnet/runtime.NET is a cross-platform runtime

shine94.tistory.com

 

* 유사난수(Pseudo-Random Number, 의사난수)

   컴퓨터가 일정한 규칙을 사용해 마치 임의의 렌덤 값처럼 생성한 수

   즉, 골고루 나오도록 만든 임의의 수

   (예) 게임에서 가챠

 

* 진짜난수(True Random Number)

   물리적 현상(방사능 붕괴, 열소음, 공기 중 전자 노이즈 등)으로부터 생성한 수

   예측 불가능, 완전한 무작위성

   (예) 암호화 키 생성

 

* 유니티의 Update()

   매 프레임 마다 호출된다

   컴퓨터 사양과 상황에 따라 프레임 속도가 달라지면 호출 간격도 달라진다

 

   [Time.deltaTime] 이전 프레임과 현재 프레임 사이의 시간 간격을 나타낸다

 

   (예) 사용자 입력 처리, UI 갱신, 애니메이션 트리거 등 일반적인 로직, 싱글 게임

   

* 유니티의 FixedUpdate()

   고정된 시간 간격으로 반복 호출된다

   기본 설정은 FPS50(0.02초 간격)이며, Physics Step이라고도 불린다

   컴퓨터 성능과 상관없이 일정한 주기를 유지한다

 

   (예) Rigidbody의 물리 이동, 물리 연산 처리, 충돌 판정, 멀티플레이어 게임에서 Physics 상태를 동기화할 때 사용

 

* 백터(Vector)

   길이(크기)와 방향을 가진 값

   위치, 이동, 힘 등을 표현할 때 사용

   Vector3, Vector2

 

* 유니티 광선(Raycast)

   광선(가상의 직선)을 쏘아 물체와의 충돌을 검사

   물체 탐지, 총알 발사, 시야 판정 등에 필수

   Physics.Raycast