no image
C# - 해쉬셋(HashSet) vs Dictionary(HashTable)
✅ HashSet이란?중복을 허용하지 않는 데이터 집합 (Set)을 구현한 자료구조내부적으로는 **해시 테이블(Hash Table)**을 사용하지만,핵심 목적은 **"중복 없는 값의 모음"**을 만드는 거야.🔍 HashSet의 특징❌ 중복 허용 안 함같은 값을 두 번 넣어도 한 번만 저장됨🔍 순서 없음넣은 순서 보장 안 됨⚡ 매우 빠름추가, 삭제, 탐색 전부 평균 O(1)📦 내부 구조키만 있고, 값은 없음 (딕셔너리는 key-value, 얘는 key만 존재)✅ HashSet 예제 (C#)using System.Collections.Generic;HashSet names = new HashSet();names.Add("Alice");names.Add("Bob");names.Add("Alice"); ..
2025.07.02
C#
no image
Unity - 스크립터블오브젝트(ScriptableObject)&예제
✅ ScriptableObject란?📌 개념 정리ScriptableObject는 MonoBehaviour처럼 Unity에서 사용하는 클래스지만,씬에 붙는 컴포넌트가 아니고, 독립적인 데이터 객체야.데이터를 자산(Asset)으로 만들어 저장하고 공유할 수 있는 방식을 제공해.✅ 언제 사용하나요?여러 객체가 동일한 데이터를 참조할 때예: 스탯, 설정값, 아이템 정보 등프리팹이나 코드와 독립적으로 데이터 관리하고 싶을 때설정 변경이 쉽고 유지보수 편함인스펙터에서 직접 데이터 입력하고 저장하고 싶을 때커스텀 에디터 연동도 쉬움✅ 간단한 예제: 캐릭터 능력치 데이터 만들기1. CharacterStats.csusing UnityEngine;[CreateAssetMenu(fileName = "NewCharacter..
2025.07.02
no image
C# - 해시테이블(HashTable) vs 딕셔너리(Dictionary)&제네릭(Generic)
✅ 해시테이블 (Hash Table)📌 개념키(key)를 해시 함수(Hash Function)에 넣어 나온 해시값을 기반으로 데이터를 저장하는 자료구조.내부적으로는 배열(array)와 연결 리스트 또는 트리 구조를 함께 사용해 충돌을 해결함.📌 동작 방식Key → 해시 함수 → 인덱스 계산계산된 인덱스에 값을 저장같은 인덱스에 이미 값이 있으면 충돌(Collision) 발생충돌 해결법: 체이닝(Chaining), 오픈 어드레싱(Open Addressing)📌 시간 복잡도 (평균적 상황 기준)삽입: O(1)삭제: O(1)탐색: O(1)※ 최악의 경우에는 O(n) (모든 키가 같은 인덱스로 해시됨)✅ 딕셔너리 (Dictionary in C#)📌 개념C#에서의 Dictionary는 해시테이블 기반으로 ..
2025.07.02
C#
no image
TIL - 내일배움캠프 2일차 TIL [CS공부 + 카드게임 팀 프로젝트](25.07.01)
1. 오늘 학습 키워드Unity, Card 시스템, 애니메이션 제한, 클릭 제한, Git 협업, Detached HEAD, ScriptableObject 개념, Update 주기, GC, 캡슐화2. 오늘 학습 한 내용을 나만의 언어로 정리하기 오전에는 컴퓨터 사이언스 관련 기초 개념을 정리했다.Unity에서의 Update, FixedUpdate, LateUpdate 주기 차이를 이해하고객체지향 원칙 중 하나인 **캡슐화(Encapsulation)**에 대해 복습했다.C#에서 **GC(Garbage Collector)**의 동작 조건과 실행 시점도 정리했으며,값 형식과 참조 형식의 차이를 통해 메모리 구조와 호출 방식을 구분했다.또한 C#의 박싱(Boxing)과 언박싱(Unboxing) 개념을 실습하며 성..
2025.07.01
no image
C# - .NET Runtime
✅ .NET 런타임이란?.NET Runtime은 C#, F#, VB.NET 같은 **.NET 언어로 만든 프로그램을 실행해주는 "실행 환경(엔진)"**이야.다시 말해, .NET 코드가 컴퓨터에서 실제로 돌아가도록 도와주는 핵심 소프트웨어야.✅ .NET 런타임이 하는 일 (핵심 역할)역할설명🧠 CLR (Common Language Runtime).NET의 핵심 엔진. 모든 .NET 프로그램은 CLR 위에서 실행됨🧼 GC (Garbage Collector)사용되지 않는 힙 메모리 자동 정리📚 타입 시스템 및 형식 검사코드에서 사용된 타입들이 안전한지 검사🧱 JIT 컴파일 (Just-In-Time)C# 코드를 실행 가능한 기계어로 실행 시에 변환🔒 보안 및 예외 처리프로그램의 오류 관리, 접근 제어 ..
2025.07.01
C#
no image
Unity - Update(), FixedUpdate(), LateUpdate()
✅ Unity의 3가지 주요 루프 함수함수 이름실행 주기용도특징Update()매 프레임마다사용자 입력, 일반 로직프레임 속도에 따라 실행 빈도 달라짐 (가변)FixedUpdate()고정 시간 간격마다물리 연산 (Rigidbody)물리 시스템과 동기화됨LateUpdate()Update() 이후카메라 추적, 뒷정리 작업모든 Update()가 끝난 후 실행 ✅ 1. Update()🔸 언제 실행됨?매 프레임마다 1번씩 실행프레임 수에 따라 실행 빈도가 달라짐 (60FPS면 초당 60번, 30FPS면 초당 30번)🔸 주로 어디에 사용?사용자 입력 처리 (키보드, 마우스 등)UI 업데이트시간 기반 이동 (예: transform.Translate(speed * Time.deltaTime))🔸 주의할 점프레임이 ..
2025.07.01
no image
C# - 캡슐화
✅ 캡슐화(Encapsulation)란?"객체의 내부 상태(데이터)를 외부로부터 숨기고, 허용된 방식으로만 접근하도록 제한하는 것."✅ 핵심 요약항목설명목적데이터를 보호하고, 잘못된 접근/수정을 방지수단접근 제한자 (private, public, protected 등) 사용결과유지보수성 증가, 의도치 않은 버그 감소, 코드 안정성 향상✅ 왜 중요한가?모든 데이터에 마음대로 접근할 수 있다면?예: 체력이 음수로 떨어진다거나, 돈이 마이너스가 되는 상황 발생캡슐화를 통해 이런 비정상적인 상황을 차단할 수 있음✅ 예제 코드 (C# 기준)❌ 잘못된 설계: 데이터가 완전 노출됨public class Player{ public int hp; // 외부에서 직접 접근 가능}Player p = new Playe..
2025.07.01
C#
no image
C# - 박싱/언박싱과 박싱/언박싱&형변환 차이
✅ 박싱(Boxing) & 언박싱(Unboxing)🔸 박싱(Boxing)값 형식(Value Type) 데이터를 **참조 형식(Reference Type)**으로 변환하는 것값 타입(예: int, float)을 object 타입에 저장하면 박싱이 발생이 과정에서 값이 힙에 복사되고, 새로운 참조 객체로 할당됨int num = 10; object obj = num; // 박싱🔸 언박싱(Unboxing)박싱된 object를 다시 원래의 값 타입으로 꺼내오는 것힙에 있는 데이터를 스택에 복사하는 작업반드시 명시적 형변환이 필요하며, 잘못된 형변환 시 런타임 오류 발생int original = (int)obj; // 언박싱🔸 단점박싱/언박싱은 메모리 할당과 복사 비용이 발생 → 성능 저하특히 루프, 게임 로..
2025.07.01
C#
반응형

✅ HashSet이란?

중복을 허용하지 않는 데이터 집합 (Set)을 구현한 자료구조
내부적으로는 **해시 테이블(Hash Table)**을 사용하지만,
핵심 목적은 **"중복 없는 값의 모음"**을 만드는 거야.


🔍 HashSet의 특징

❌ 중복 허용 안 함 같은 값을 두 번 넣어도 한 번만 저장됨
🔍 순서 없음 넣은 순서 보장 안 됨
⚡ 매우 빠름 추가, 삭제, 탐색 전부 평균 O(1)
📦 내부 구조 키만 있고, 값은 없음 (딕셔너리는 key-value, 얘는 key만 존재)

✅ HashSet 예제 (C#)

using System.Collections.Generic;

HashSet<string> names = new HashSet<string>();

names.Add("Alice");
names.Add("Bob");
names.Add("Alice");  // 중복! 무시됨

Console.WriteLine(names.Count); // 출력: 2
Console.WriteLine(names.Contains("Bob")); // true

✅ HashSet vs Dictionary (or Hashtable)

키와 값 키만 존재 키와 값 존재
목적 중복 없는 목록 키로 값을 매핑
내부 구현 Hash Table 기반 Hash Table 기반
사용 예 방문 여부 확인, 유니크 목록 설정값 저장, 데이터 검색

✅ 언제 쓰나?

중복 제거 중복 있는 리스트에서 유니크한 값만 뽑을 때
빠른 포함 여부 확인 어떤 값이 존재하는지 빠르게 검사할 때
태그/이름/고유값 저장 "이미 처리했는가?"를 추적할 때

✅ 예: 방문한 적 있는 위치 추적

HashSet<Vector2Int> visited = new HashSet<Vector2Int>();

Vector2Int current = new Vector2Int(2, 3);

if (!visited.Contains(current))
{
    visited.Add(current);
    // 처음 방문한 위치 처리
}

📌 핵심 요약

HashSet<T>는 딕셔너리에서 값(value)을 없앤 버전이라고 생각하면 쉬워.
딕셔너리: key → value
해시셋: key만 저장 (중복 없음)

 

오 해쉬셋과 딕셔너리가 둘다 해시테이블 기반으로 만들어졌다는게 좀 신기했다. 딕셔너리는 해시테이블의 상위호환이지 해시테이블 기반인줄은 몰랐다. 다시 GPT에게 물어보니 해시테이블 기반이 맞다고 한다.

또 궁금한게 생겼다. 딕셔너리에서는 값을 없앤 버전이라고 언급하는데 그럼 딕셔너리는 중복이 허용 가능한가? 싶었다 다시 GPT에게 물어보니

 

딕셔너리(Dictionary)는 키(key) 중복을 허용하지 않아.
✅ 단, 값(value) 은 중복될 수 있어.


✅ 딕셔너리에서 중복이 되는 부분과 안 되는 부분

항목중복 가능 여부설명
Key ❌ 불가능 같은 키로 두 번 Add() 하면 예외 발생
Value ✅ 가능 여러 키가 같은 값을 가질 수 있음

✅ 예시로 확인해보자

 
Dictionary<string, int> dict = new Dictionary<string, int>();

dict.Add("apple", 1);
dict.Add("banana", 1);   // value는 중복 가능
dict.Add("apple", 2);    // ❌ 오류! 키 중복
System.ArgumentException: 항목이 이미 추가되었습니다.

 

즉,

  • "apple"이라는 키가 두 번 들어가는 건 안됨
  • 값인 1이 두 번 들어가는 건 가능함

✅ 해시셋은?

  • 아예 Key = Value인 구조야.
  • 따라서 모든 값 자체가 고유해야 함
  • 즉, "apple"을 두 번 넣으면 무시됨.

🧠 핵심 요약

자료구조중복 가능 여부
Dictionary ❌ 키는 중복 불가 / ✅ 값은 중복 가능
HashSet ❌ 값 중복 불가 (값 = 키)

음..이렇게 된다면 해시테이블도 궁금해졌다.

✅ Hashtable도 Dictionary와 마찬가지로

항목중복 가능 여부
Key ❌ 중복 불가
Value ✅ 중복 가능

 

확실히 딕셔너리도 해시테이블 기반으로 만들어진거다 보니 키값은 둘다 똑같이 중복이 안된다고한다.

정리하자면

HashSet - 키값만 있음, 키값 중복안됨. 약간 데이터 저장용도일까...정보를 넣었는지 안넣었는지 구별할때나 있는지 없는지 구별할떄 많이 사용할 듯 하다.

Dictionary - 키값, 값 둘다있음. 하지만 키값은 중복안됨.

HashTable - 키값, 값 둘다음. 하지만 키값은 중복안됨.

여기서봤을떄는 딕셔너리와 해시테이블이 같아 보이지만. 명확하게 차이가 나는걸 알고있다.

이렇게 계속 비교하면서 공부하는게 참 재밌는거같다

https://dev-jen.tistory.com/entry/%ED%95%B4%EC%8B%9C%ED%85%8C%EC%9D%B4%EB%B8%94HashTable-vs-%EB%94%95%EC%85%94%EB%84%88%EB%A6%ACDictionary%EC%A0%9C%EB%84%A4%EB%A6%ADGeneric

 

C# - 해시테이블(HashTable) vs 딕셔너리(Dictionary)&제네릭(Generic)

✅ 해시테이블 (Hash Table)📌 개념키(key)를 해시 함수(Hash Function)에 넣어 나온 해시값을 기반으로 데이터를 저장하는 자료구조.내부적으로는 배열(array)와 연결 리스트 또는 트리 구조를 함께 사용

dev-jen.tistory.com

 

반응형

'C#' 카테고리의 다른 글

C# - Virtual & abstract  (0) 2025.07.03
C# - 자료구조  (1) 2025.07.02
C# - 해시테이블(HashTable) vs 딕셔너리(Dictionary)&제네릭(Generic)  (0) 2025.07.02
C# - .NET Runtime  (1) 2025.07.01
C# - 캡슐화  (1) 2025.07.01
반응형

✅ ScriptableObject란?

📌 개념 정리

  • ScriptableObject는 MonoBehaviour처럼 Unity에서 사용하는 클래스지만,
  • 씬에 붙는 컴포넌트가 아니고, 독립적인 데이터 객체야.
  • 데이터를 자산(Asset)으로 만들어 저장하고 공유할 수 있는 방식을 제공해.

✅ 언제 사용하나요?

여러 객체가 동일한 데이터를 참조할 때 예: 스탯, 설정값, 아이템 정보 등
프리팹이나 코드와 독립적으로 데이터 관리하고 싶을 때 설정 변경이 쉽고 유지보수 편함
인스펙터에서 직접 데이터 입력하고 저장하고 싶을 때 커스텀 에디터 연동도 쉬움

✅ 간단한 예제: 캐릭터 능력치 데이터 만들기

1. CharacterStats.cs

using UnityEngine;

[CreateAssetMenu(fileName = "NewCharacterStats", menuName = "ScriptableObjects/CharacterStats")]
public class CharacterStats : ScriptableObject
{
    public string characterName;
    public int maxHP;
    public int attackPower;
    public float moveSpeed;
}

2. 생성 방법

  • Unity 에디터에서 우클릭 → Create → ScriptableObjects → CharacterStats
  • 이름을 WarriorStats, MageStats 등으로 지정하고 값 입력

3. 사용하는 스크립트

public class Player : MonoBehaviour
{
    public CharacterStats stats;

    private void Start()
    {
        Debug.Log($"{stats.characterName}의 공격력: {stats.attackPower}");
    }
}
  • Player 오브젝트에 붙이고, stats 필드에 ScriptableObject 자산을 할당하면 끝!

✅ ScriptableObject vs MonoBehaviour

씬에 존재 ❌ (씬에 안 붙음) ✅ (오브젝트에 붙임)
메모리 효율 ✅ 매우 좋음 ❌ 반복 사용 시 비효율
역할 데이터 저장, 설정 동작 로직, 이벤트 처리
재사용 여러 오브젝트가 참조 가능 오브젝트마다 개별

 


✅ 장점 정리

  • ✔️ 씬 독립적 데이터 관리 가능 (게임 밸런스 조정 시 유리)
  • ✔️ 프리팹 재사용 시 같은 데이터를 공유할 수 있어 메모리 절약
  • ✔️ 버전 관리에 유리 (데이터가 파일로 존재하니까 Git에도 딱!)
  • ✔️ 유닛 테스트에 적합

✅ 단점 or 주의사항

  • ScriptableObject는 **상태(state)**를 저장하기보단 설정값(config) 저장에 적합함
  • 런타임에 값을 바꾸면 에디터에 저장된 자산이 수정될 수도 있으므로 주의

✅ 실생활 비유

  • MonoBehaviour는 "게임에 나오는 배우(오브젝트)"
  • ScriptableObject는 "그 배우가 참고하는 대본(데이터)"

으음 데이터로 활용하는것은 너무 좋아보인다 처음 이걸 봤을때 왜 이걸 몰랐을까? 싶었다 엄청 유용하게 많이 사용될듯하다 보통 인벤토리 시스템에 많이 사용하는거 같다 스킬/아이템 데이터등등..

간단하게 유니티로 뭐라도 만들어 보자!

 

대충 요약하자면

📦 전체 구성 요약

1. ScriptableObject 기반 아이템 데이터 관리

  • Item_ScriptableObject 클래스 생성
  • 인스펙터에서 여러 개의 아이템 데이터를 .asset 파일로 생성 (ItemData1~4)
  • 각 아이템은 고유 번호, 이름, 설명, 파워 등의 정보를 가짐

2. 아이템 오브젝트 (Item)

  • ItemObject 스크립트 부착
  • 각각의 오브젝트가 하나의 ScriptableObject 참조
  • Tag는 "Item"으로 지정

3. 플레이어

  • WASD 키 입력으로 2D 이동
  • Rigidbody2D + Collider2D 구성
  • Item과 충돌 시 해당 데이터 획득

4. UI 시스템

  • ItemUIManager 스크립트로 Text 컴포넌트 제어
  • 아이템 정보 표시 및 초기화 담당

흠..근데 사실 고유 번호는 필요 없었을거같다. 이런식으로 아이템 정보를 저장해서 사용할수있는걸 알게됐다!

 

나머지 코드

Item_ScriptableObject.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName ="ItemData", menuName = "ScriptableObject/ItemData")]
public class Item_ScriptableObject : ScriptableObject
{
    public int itemNum;
    public string itemName;
    public string iteminfo;
    public int itemPower;
}

ItemObject.cs - 아이템에 들어가는 스크립트 - Tag Item으로 추가해줘야한다.

using UnityEngine;

public class ItemObject : MonoBehaviour
{
    public Item_ScriptableObject itemData;
}

ItemUIManager.cs 이다 여기서 아이템의 설명과 정보를 출력

using UnityEngine;
using UnityEngine.UI;

public class ItemUIManager : MonoBehaviour
{
    public Text nameText;
    public Text infoText;
    public Text powerText;
    public GameObject panel;

    private void Start()
    {
        panel.SetActive(false);
    }

    public void ShowItemInfo(Item_ScriptableObject item)
    {
        panel.SetActive(true);
        nameText.text = $"이름: {item.itemName}";
        infoText.text = $"설명: {item.iteminfo}";
        powerText.text = $"파워: {item.itemPower}";
    }

    public void HideInfo()
    {
        panel.SetActive(false);
        nameText.text = "";
        infoText.text = "";
        powerText.text = "";
    }
}

Player.cs 이다. Item과 닿는다면 UI매니저를 이용해서 아이템의 정보를 받아온다.

using UnityEngine;

public class Player : MonoBehaviour
{
    public ItemUIManager uiManager;

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Item"))
        {
            ItemObject itemObj = other.GetComponent<ItemObject>();
            if (itemObj != null && itemObj.itemData != null)
            {
                uiManager.ShowItemInfo(itemObj.itemData);
            }
        }
    }

    private void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Item"))
        {
            uiManager.HideInfo();
        }
    }
}

 

나머지 코드 1개는 PlayerMovement인데 간단하니까 넘어가겠다.

반응형
반응형

✅ 해시테이블 (Hash Table)

📌 개념

  • 키(key)를 해시 함수(Hash Function)에 넣어 나온 해시값을 기반으로 데이터를 저장하는 자료구조.
  • 내부적으로는 배열(array)와 연결 리스트 또는 트리 구조를 함께 사용해 충돌을 해결함.

📌 동작 방식

  1. Key → 해시 함수 → 인덱스 계산
  2. 계산된 인덱스에 값을 저장
  3. 같은 인덱스에 이미 값이 있으면 충돌(Collision) 발생
  4. 충돌 해결법: 체이닝(Chaining), 오픈 어드레싱(Open Addressing)

📌 시간 복잡도 (평균적 상황 기준)

  • 삽입: O(1)
  • 삭제: O(1)
  • 탐색: O(1)

※ 최악의 경우에는 O(n) (모든 키가 같은 인덱스로 해시됨)


✅ 딕셔너리 (Dictionary in C#)

📌 개념

  • C#에서의 Dictionary<TKey, TValue>는 해시테이블 기반으로 구현된 제네릭 키-값(key-value) 쌍 자료구조.
  • 즉, 해시테이블을 제네릭 버전으로 구현한 클래스라고 보면 됨.

📌 사용 예시

Dictionary<string, int> ages = new Dictionary<string, int>();
ages["Alice"] = 25;
ages["Bob"] = 30;

Console.WriteLine(ages["Alice"]);  // 25

📌 주요 메서드

  • Add(key, value) : 새 항목 추가
  • Remove(key) : 항목 제거
  • ContainsKey(key) : 특정 키 존재 여부 확인
  • TryGetValue(key, out value) : 키가 있으면 값을 out 파라미터로 반환

🔍 해시테이블 vs 딕셔너리 차이점

제네릭 지원 ❌ (object 기반)
타입 안정성 낮음 (박싱/언박싱 필요) 높음
성능 상대적으로 느릴 수 있음 더 빠름
쓰레드 안전 기본적으로 안전하지 않음 마찬가지 (별도 처리 필요)
사용 권장 구형 코드 유지 보수시 신규 개발시 권장

 

사실 해시테이블의 상위호환이 딕셔너리 라고 한다. 해시테이블은 사용할떄마다 박싱/언박싱을 하기 때문에 너무 비효율 적이다. 쓰레드까지 들어간다면 솔직히 잘 모르겠다.. 어떻게 안전하지 않다는 기준은 뭔진 모르겠다. 

그리고 제네릭 지원이라는 것이 궁금했다. 제너릭이란건 자세히 뭘까

 

✅ 제네릭이란?

  • 하나의 클래스나 메서드가 다양한 데이터 타입을 처리할 수 있도록 해주는 기능
  • 코드를 타입에 의존하지 않고 작성하고, 나중에 사용할 때 구체적인 타입을 지정
  • 성능이 좋고 타입 안정성도 보장됨 (컴파일 타임에 타입 검사)

🔍 예시 (제네릭 없이 작성한 코드)

ArrayList list = new ArrayList();
list.Add(1);          // int
list.Add("hello");    // string

int num = (int)list[0];  // 형변환 필요 (박싱/언박싱)
  • 타입이 object이기 때문에 어떤 값이든 넣을 수 있지만,
  • 형변환이 필요하고, 런타임 오류가 발생할 수 있음

✅ 제네릭 사용 예시

List<int> intList = new List<int>();
intList.Add(1);
intList.Add(2);

int num = intList[0]; // 형변환 필요 없음!
  • List<int>는 int형만 저장 가능
  • 컴파일 타임에 타입 검사 가능 → 오류 예방
  • 형변환이 없어져서 성능도 좋아짐

🔧 직접 만든 제네릭 클래스 예시

 
public class Box<T>  // T는 타입 매개변수 (Type Parameter)
{
    public T item;

    public void SetItem(T value)
    {
        item = value;
    }

    public T GetItem()
    {
        return item;
    }
}

💡 왜 제네릭을 사용할까?

이유설명
코드 재사용성 하나의 코드로 다양한 타입 처리 가능
타입 안정성 컴파일 타임에 타입 검사 가능
성능 향상 박싱/언박싱 제거로 메모리/속도 효율적

흠..GPT가 BOX<T>라는 예시를 줬는데 이 <T>가 뭔지 정확히 모르겠다 잘 사용하지 않기도 했고. 그래서 물어봤다.

 

✅ Box<T>란?

📦 정의

  • Box<T>는 "어떤 타입 T의 데이터를 담을 수 있는 상자"를 의미하는 클래스야.
  • 여기서 T는 타입 매개변수(Type Parameter) 로, 사용할 때 구체적인 타입으로 대체돼.
public class Box<T>
{
    public T item;

    public void SetItem(T value)
    {
        item = value;
    }

    public T GetItem()
    {
        return item;
    }
}

✅ 핵심 개념

용어설명
T 타입 매개변수. 보통 T(Type), K(Key), V(Value) 같은 문자로 씀
Box<T> T라는 타입을 나중에 지정할 수 있는 클래스
재사용성 Box<int>, Box<string> 등으로 여러 타입에 재사용 가능
 

✅ 실제 사용 예

Box<int> intBox = new Box<int>();
intBox.SetItem(10);                  // int 타입 사용
Console.WriteLine(intBox.GetItem());  // 출력: 10

Box<string> strBox = new Box<string>();
strBox.SetItem("hello");            // string 타입 사용
Console.WriteLine(strBox.GetItem());  // 출력: hello
  • Box<int>라고 선언하면 T는 int로 바뀌고,
  • Box<string>이라고 하면 T는 string으로 바뀌는 거야.

✅ 왜 이렇게 쓰는 걸까?

  1. 타입마다 클래스를 일일이 만들 필요 없음
  2. 형변환 없이 안전하게 값 사용 가능
  3. 컴파일 시 타입 검사 가능 → 오류 예방

✅ Box<T>를 실생활에 비유하면?

  • Box<T>는 "어떤 물건이든 담을 수 있는 상자"
  • 사용할 때 "이 상자에는 **책(int)**만 담을 거야", 혹은 "**편지(string)**만 담을 거야" 하고 말해주는 느낌이야.

흠..일단 그럼 T는 다양한 형식을 받을 수 있지만 그 중에 1종류만 받는다는 느낌이 강하다 생각했다 그러면 <T>라면 정말 어떤 타입이 올지 몰라서 대기하는 느낌이고 평소에 게임을 만든다면 <int>등등 정확한 타입을 써서 정의내리는게 더 깔끔할듯하다. 

✅ 왜 Box<int> 같은 걸 쓸까?

1. 타입별 클래스를 중복 작성할 필요 없게 해줌

❌ 제네릭 없이 하면:

public class IntBox {
    public int item;
}

public class StringBox {
    public string item;
}
  • int, string, float… 다 다른 클래스를 만들어야 해.
  • 유지보수 힘듦 + 코드 중복

✅ 제네릭을 쓰면:

public class Box<T> {
    public T item;
}
  • 한 번만 만들면 어떤 타입이든 다 쓸 수 있어: Box<int>, Box<string>, Box<float>...

2. 타입 안정성과 성능을 동시에 보장

❌ object 기반이면:

 
public class ObjectBox {
    public object item;
}
ObjectBox box = new ObjectBox();
box.item = 10;

int value = (int)box.item; // 형변환 필요 → 실수로 string을 넣었다면? → 런타임 오류
  • object는 어떤 타입이든 담을 수 있지만 형변환 필요하고, 런타임 오류 가능성 있음

✅ 제네릭 쓰면:

Box<int> box = new Box<int>();
box.item = 10;

int value = box.item; // 형변환 없음! 타입 안전!
  • 컴파일 타임에 타입 검사
  • 형변환 없어져서 성능도 더 좋음

3. 자료구조를 만들 때 필수

예를 들어, 우리가 직접 Stack, Queue, List 같은 자료구조를 만든다고 해보자.

public class MyStack<T> {
    private List<T> data = new List<T>();

    public void Push(T item) {
        data.Add(item);
    }

    public T Pop() {
        T item = data[data.Count - 1];
        data.RemoveAt(data.Count - 1);
        return item;
    }
}

📌 결론

Box<int>는 그냥 "정수를 담는 상자"고, 제네릭을 사용함으로써 우리는

  • 중복 코드 없이
  • 타입 안정성 확보하면서
  • 다양한 타입에 대해 유연하게 대응 가능한 클래스를 만들 수 있어.

 

음.. 그렇다고한다 확실히 제네릭을 쓰는게 훨씬 효율적이고 형변환도 필요없으니 좋은듯하다.

반응형

'C#' 카테고리의 다른 글

C# - 자료구조  (1) 2025.07.02
C# - 해쉬셋(HashSet) vs Dictionary(HashTable)  (2) 2025.07.02
C# - .NET Runtime  (1) 2025.07.01
C# - 캡슐화  (1) 2025.07.01
C# - 박싱/언박싱과 박싱/언박싱&형변환 차이  (0) 2025.07.01
반응형

1. 오늘 학습 키워드

Unity, Card 시스템, 애니메이션 제한, 클릭 제한, Git 협업, Detached HEAD, ScriptableObject 개념, Update 주기, GC, 캡슐화


2. 오늘 학습 한 내용을 나만의 언어로 정리하기

 

오전에는 컴퓨터 사이언스 관련 기초 개념을 정리했다.

  • Unity에서의 Update, FixedUpdate, LateUpdate 주기 차이를 이해하고
  • 객체지향 원칙 중 하나인 **캡슐화(Encapsulation)**에 대해 복습했다.
  • C#에서 **GC(Garbage Collector)**의 동작 조건과 실행 시점도 정리했으며,
  • 값 형식과 참조 형식의 차이를 통해 메모리 구조와 호출 방식을 구분했다.

또한 C#의 박싱(Boxing)과 언박싱(Unboxing) 개념을 실습하며 성능 이슈를 확인했고,
컬렉션 구조인 Hashtable과 Dictionary의 차이점, 제네릭 사용 여부, 검색 속도 특성 등도 비교하며 학습했다.

 

오후는 Unity 팀 프로젝트에서 카드 시스템을 다듬는 데 집중했다.

카드가 애니메이션 중일 때 다른 카드가 클릭되지 않도록 static bool canClick을 사용해 클릭 제한 로직을 구현했고, 카드 2장까지만 열리고 3번째 카드를 클릭하면 기존 2장을 자동으로 닫는 방식으로 OpenCard() 로직도 수정했다.

GitHub Desktop에서 Detached HEAD 상태에 빠졌을 때 브랜치로 다시 Checkout하는 방법도 익혔고, Publish branch 버튼이 비활성화되는 이유와 해결 방법도 이해하게 되었다.

중간에 폭탄 카드(idx == -1) 처리를 시도했지만, Sprite 대신 프리팹이 들어있는 구조라서 일단 내일 다시 시도하기로 했다.

또한 ScriptableObject가 뭔지, 어떤 구조로 활용되는지 예제를 통해 개념적으로 정리했다.

 

팀 프로젝트

  • 2장씩 넘어가게 (나머지는 닫힘) (완료)
  • 카드 애니메이션 제작 (완료)
  • 카드 기본 이미지 꾸미기 (완료)
  • 성공했을떄 UI Particle 추가 (완료)

3. 학습하며 겪었던 문제점 & 에러

🔸 정의

  • 카드 애니메이션 중 다른 카드가 눌리는 문제
  • GitHub에서 Publish 버튼이 비활성화되고 Detached HEAD 상태가 나타남

🔸 시도

  • canClick bool 변수를 통해 클릭 제한 제어
  • Invoke()로 애니메이션 후 다시 클릭 가능하게 함
  • GitHub 브랜치 상태 및 Checkout 관련 메뉴 확인

🔸 해결 방법

  • OpenCard()에 canClick 조건 추가
  • Invoke("EnableClick", 0.6f) 방식으로 타이밍 제어
  • 브랜치 복귀하여 정상적인 상태로 되돌림

🔸 새롭게 알게 된 점

  • Detached HEAD는 브랜치가 아닌 커밋만 보고 있는 상태이며, 이 상태에선 커밋을 푸시할 수 없음
  • ScriptableObject는 게임 데이터 저장 및 재사용에 유용한 구조이며, 코드와 데이터를 분리할 수 있음

🔸 다시 만나게 된다면?

  • 애니메이션이 끝나는 정확한 시점을 Animation Event로 관리하면 더 안정적일 것
  • Git 상태는 항상 브랜치 이름과 History를 먼저 확인하고 작업할 것

4. 내일 학습 할 것

CS 지식, 팀 프로젝트 나머지 보완 문제


5. 메모

스택 - 정적으로 메모리에 할당. (후입선출, LIFO)

힙 - 동적으로 메모리에 할당. (선입선출, FIFO) (GC가 이 영역의 사용되지 않는 데이터들을 소멸시킴 - 언제?)

value type(값 형식) - 데이터를 메모리의 스택영역에 할당. 스택 메모리 공간에 (값)을 가지고 있다.

reference type(참조 형식) - 데이터를 힙영역에 할당. 스택 메모리 공간에(주소)를 가지고 있다. (그럼 데이터는 힙에있고 스택에는 주소값만?)

박싱 - 값 형식을 참조 형식으로 변환하는 것. 스택에 있는 값을 복사하여 힙에 할당한다.

언박싱 - 박싱했던 값을 다시 원상태로 복귀 시키는 것. 힙에 있던 데이터를 스택으로 복사한다. 힙에 가비지가 쌓이게 된다.(언제?)

해시테이블도 키값으로 값을 찾음 - 딕셔너리(상위호환)

해시테이블은 사용할때 언박싱을 해줘야한다. - 오? - 딕셔너리는 필요없음

최대기반의 GC컬렉터 - 마크 1,2,3 세대가 오래될수록 --

 

팀프로젝트 중 오류 - 즐거웠다

    public void Setting(int number)
    {
        idx = number;
        frontImage.sprite = Resources.Load<Sprite>($"Team_{idx}");

        if (frontImage.sprite != null)
        {
            frontImage.transform.localScale = Vector3.one;

            float spriteWidth = frontImage.sprite.bounds.size.x;
            float spriteHeight = frontImage.sprite.bounds.size.y;

            float targetWidth = 0.8f;
            float targetHeight = 1f;

            float scaleX = targetWidth / spriteWidth;
            float scaleY = targetHeight / spriteHeight;

            frontImage.transform.localScale = new Vector3(scaleX, scaleY, 1f);
        }
    }

카드 스크립트중 셋팅값에서 카드가 자꾸 이상하게 스케일이 커지고 작아지는 문제가 있었다. 그래서 이것저것 건드려보고 애니메이션에서도 스케일값을 수정해봤는데 이상했었다. 근데이제 진원님이 만드신 CardMover라는 코드에서 카드의 초기 스케일값과 마지막 스케일값을 조정하는 변수를 발견했다!! 이걸 발견하기전에는 카드값이 제각각으로 막 커지고 작아졌었는데 이 값을 수정하니 완벽하게 됐다.

이 과정을 겪으며 카드가 이상하게 스케일값이 왔다갔다하며 화면을 팀원들과 같이 봤었는데 다들 왜이렇게 되냐며 즐거웠다ㅋㅋㅋ 이렇게 팀프로젝트를 진행하며 재밌는 경험도하고 같이 웃으며 팀 프로젝트를 진행하니 나도 즐거웠다!!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class CardMover : MonoBehaviour
{
    public Card _card = null;

    [Header("카드 이동 시간 / 카드 딜레이 시간")]
    public float moveDuration = 0.5f;           // 이동 시간
    public float delayBetween = 0.1f;           // 딜레이 시간

    [Header("이동 타입")]
    public Ease moveEase = Ease.OutBack;        // 이동 타입

    [Header("카드의 초기 크기 ~ 최종 크기")]
    public Vector3 startScale = Vector3.zero;   // 시작 스케일
    public Vector3 endScale = Vector3.one;      // 끝 스케일

    public void Show(Vector2 vec_TargetPos, Card card, int index)
    {
        if (_card != null) return;
        _card = card;

        Transform tf = _card.transform;

        // 초기화
        tf.localPosition = Vector3.zero;
        tf.localScale = startScale;

        float delay = delayBetween * index;

        // 로컬 위치 이동
        tf
          .DOLocalMove(vec_TargetPos, moveDuration)
          .SetDelay(delay)
          .SetEase(moveEase);

        // 스케일 애니메이션
        tf
          .DOScale(endScale, moveDuration)
          .SetDelay(delay)
          .SetEase(moveEase);
    }

    private void OnDisable()
    {
        _card = null;
    }
}

결정적인 CardMover의 스크립트였다.


오늘 오전에 공부한 내용

https://dev-jen.tistory.com/entry/C-Unity-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%ED%84%B0GC

 

C# Unity - 가비지 컬렉터(GC) 자동실행기준

✅ 가비지 컬렉터(GC)의 역할이란?더 이상 사용되지 않는 힙의 메모리를 자동으로 찾아서 정리해주는 시스템즉,메모리 누수 방지수동으로 메모리 해제하지 않아도 됨 (delete, free 필요 없음)✅ GC

dev-jen.tistory.com

https://dev-jen.tistory.com/entry/C-%EB%B0%95%EC%8B%B1%EC%96%B8%EB%B0%95%EC%8B%B1%EA%B3%BC-%EB%B0%95%EC%8B%B1%EC%96%B8%EB%B0%95%EC%8B%B1%ED%98%95%EB%B3%80%ED%99%98-%EC%B0%A8%EC%9D%B4

 

C# - 박싱/언박싱과 박싱/언박싱&형변환 차이

✅ 박싱(Boxing) & 언박싱(Unboxing)🔸 박싱(Boxing)값 형식(Value Type) 데이터를 **참조 형식(Reference Type)**으로 변환하는 것값 타입(예: int, float)을 object 타입에 저장하면 박싱이 발생이 과정에서 값이 힙

dev-jen.tistory.com

https://dev-jen.tistory.com/entry/C-%EC%BA%A1%EC%8A%90%ED%99%94

 

C# - 캡슐화

✅ 캡슐화(Encapsulation)란?"객체의 내부 상태(데이터)를 외부로부터 숨기고, 허용된 방식으로만 접근하도록 제한하는 것."✅ 핵심 요약항목설명목적데이터를 보호하고, 잘못된 접근/수정을 방지수

dev-jen.tistory.com

https://dev-jen.tistory.com/entry/Unity-Update-FixedUpdate-LateUpdate

 

Unity - Update(), FixedUpdate(), LateUpdate()

✅ Unity의 3가지 주요 루프 함수함수 이름실행 주기용도특징Update()매 프레임마다사용자 입력, 일반 로직프레임 속도에 따라 실행 빈도 달라짐 (가변)FixedUpdate()고정 시간 간격마다물리 연산 (Rigidb

dev-jen.tistory.com

https://dev-jen.tistory.com/entry/C-NET-Runtime

 

C# - .NET Runtime

✅ .NET 런타임이란?.NET Runtime은 C#, F#, VB.NET 같은 **.NET 언어로 만든 프로그램을 실행해주는 "실행 환경(엔진)"**이야.다시 말해, .NET 코드가 컴퓨터에서 실제로 돌아가도록 도와주는 핵심 소프트웨

dev-jen.tistory.com

 

반응형

C# - .NET Runtime

Dev_Jen
|2025. 7. 1. 12:12
반응형

✅ .NET 런타임이란?

.NET Runtime은 C#, F#, VB.NET 같은 **.NET 언어로 만든 프로그램을 실행해주는 "실행 환경(엔진)"**이야.
다시 말해, .NET 코드가 컴퓨터에서 실제로 돌아가도록 도와주는 핵심 소프트웨어야.


✅ .NET 런타임이 하는 일 (핵심 역할)

역할설명
🧠 CLR (Common Language Runtime) .NET의 핵심 엔진. 모든 .NET 프로그램은 CLR 위에서 실행됨
🧼 GC (Garbage Collector) 사용되지 않는 힙 메모리 자동 정리
📚 타입 시스템 및 형식 검사 코드에서 사용된 타입들이 안전한지 검사
🧱 JIT 컴파일 (Just-In-Time) C# 코드를 실행 가능한 기계어로 실행 시에 변환
🔒 보안 및 예외 처리 프로그램의 오류 관리, 접근 제어 등을 담당
 

✅ .NET 프로그램 실행 과정 요약

  1. C# 코드를 작성
  2. 컴파일 → **IL (중간 언어, Intermediate Language)**로 변환
  3. 실행 시 .NET 런타임(CLR)이
    • IL 코드를 기계어로 변환(JIT)
    • GC로 메모리 관리
    • 예외 처리, 타입 검사 등 실행 환경 제공
  4. 최종적으로 프로그램이 실행됨

✅ .NET Runtime 구성 요소

구성요소설명
CLR (Common Language Runtime) 핵심 실행 엔진
JIT Compiler IL을 기계어로 즉석에서 번역
GC (Garbage Collector) 자동 메모리 관리
CTS (Common Type System) 모든 .NET 언어가 공유하는 타입 규칙
CLS (Common Language Specification) 언어 간 호환성을 위한 최소 규칙
BCL (Base Class Library) System.String, List<T>, Math 등 기본 라이브러리 모음
 

✅ Unity랑 .NET은 어떤 관계?

  • Unity는 C#을 사용하는데, Mono / IL2CPP / CoreCLR 같은 .NET 호환 런타임을 사용해
  • Unity에서의 GC, List<T>, object, Exception 등도 다 .NET 런타임 기반 기능이야

✅ 정리 한 줄 요약

.NET 런타임은 C# 프로그램이 돌아가게 해주는 실행 엔진이며, GC, 예외 처리, 타입 검사, JIT 컴파일 등을 자동으로 담당한다.

반응형
반응형

✅ Unity의 3가지 주요 루프 함수

함수 이름실행 주기용도특징
Update() 매 프레임마다 사용자 입력, 일반 로직 프레임 속도에 따라 실행 빈도 달라짐 (가변)
FixedUpdate() 고정 시간 간격마다 물리 연산 (Rigidbody) 물리 시스템과 동기화
LateUpdate() Update() 이후 카메라 추적, 뒷정리 작업 모든 Update()가 끝난 후 실행
 

✅ 1. Update()

🔸 언제 실행됨?

  • 매 프레임마다 1번씩 실행
  • 프레임 수에 따라 실행 빈도가 달라짐 (60FPS면 초당 60번, 30FPS면 초당 30번)

🔸 주로 어디에 사용?

  • 사용자 입력 처리 (키보드, 마우스 등)
  • UI 업데이트
  • 시간 기반 이동 (예: transform.Translate(speed * Time.deltaTime))

🔸 주의할 점

  • 프레임이 떨어지면 Update()도 늦어짐 → 물리 연산에 부적절

✅ Update()는 **컴퓨터의 성능(FPS)**에 따라 호출 빈도가 달라진다

🔹 요점 정리:

  • Update()는 렌더링 프레임마다 1번씩 호출
  • 그래서 컴퓨터 성능이 좋고 FPS가 높으면 자주 실행
  • 반대로 성능이 낮으면 실행 간격이 늘어남

✅ 2. FixedUpdate()

🔸 언제 실행됨?

  • 물리 프레임마다 고정 간격으로 실행됨
    • 기본값: 0.02초마다 (50회/초)

🔸 주로 어디에 사용?

  • Rigidbody를 사용하는 물리 기반 움직임
  • 힘(AddForce) 적용
  • 충돌 감지 처리

🔸 주의할 점

  • Time.deltaTime 대신 Time.fixedDeltaTime 사용
  • Input.GetKey()는 여기서 사용 X → 입력은 Update()에서 받고, 결과만 전달해야 함

✅ 3. LateUpdate()

🔸 언제 실행됨?

  • 모든 Update()가 끝난 후, 한 프레임 내에서 한 번 실행

🔸 주로 어디에 사용?

  • 카메라 추적 로직
  • 캐릭터 움직임이 모두 끝난 뒤에 카메라 위치를 갱신할 때
  • 뷰포트나 UI 위치 정렬

🔎 이렇게 하면 플레이어가 움직인 이후에 카메라가 따라가기 때문에 딜레이 없이 자연스러움


✅ 정리 비교표

항목UpdateFixedUpdateLateUpdate
실행 주기 프레임마다 (가변) 고정 간격 (기본 0.02초) 프레임마다, Update 후
입력 처리 ✅ 사용함 ❌ 부적절 ❌ 부적절
물리 처리 ❌ 부정확함 ✅ 정확함 ❌ 부적절
카메라 추적 ❌ 비자연스러움 ❌ 부적절 ✅ 이상적
Rigidbody 조작 ❌ 피해야 함 ✅ 사용해야 함 ❌ 사용 안 함
 

✅ 언제 뭘 써야 할까?

목적사용 함수
키보드 입력 감지 Update()
플레이어의 위치 이동 (비물리) Update() + Time.deltaTime
Rigidbody 이동, 점프, 힘 적용 FixedUpdate()
카메라가 캐릭터를 따라가도록 설정 LateUpdate()
애니메이션 이후 UI 위치 조정 LateUpdate()

 

흠... 내가 알기로는 멀티플레이 할떄도 FixedUpdate()를 써야하는걸로 알고있다. Update()로 하게되면 성능 좋은 컴퓨터가 더 호출이 빨라서 유리할수도 있다고 들었다.

반응형

C# - 캡슐화

Dev_Jen
|2025. 7. 1. 11:03
반응형

✅ 캡슐화(Encapsulation)란?

"객체의 내부 상태(데이터)를 외부로부터 숨기고, 허용된 방식으로만 접근하도록 제한하는 것."


✅ 핵심 요약

항목설명
목적 데이터를 보호하고, 잘못된 접근/수정을 방지
수단 접근 제한자 (private, public, protected 등) 사용
결과 유지보수성 증가, 의도치 않은 버그 감소, 코드 안정성 향상

✅ 왜 중요한가?

  • 모든 데이터에 마음대로 접근할 수 있다면?
    • 예: 체력이 음수로 떨어진다거나, 돈이 마이너스가 되는 상황 발생
  • 캡슐화를 통해 이런 비정상적인 상황을 차단할 수 있음

✅ 예제 코드 (C# 기준)

❌ 잘못된 설계: 데이터가 완전 노출됨

public class Player
{
    public int hp;  // 외부에서 직접 접근 가능
}

Player p = new Player();
p.hp = -100; // 💥 논리적으로 말이 안 되는 상태

✅ 캡슐화 적용 예시

public class Player
{
    private int hp = 100; // 외부에서 직접 접근 불가

    public int HP
    {
        get { return hp; }
        set
        {
            if (value >= 0) hp = value;
        }
    }
}
  • 이제 외부에서는 HP 프로퍼티로만 접근 가능
  • if (value >= 0) 같은 검증 로직도 넣을 수 있어

✅ Unity에서 캡슐화 예시

public class Enemy : MonoBehaviour
{
    [SerializeField] private float speed = 3.0f;

    public void SetSpeed(float value)
    {
        if (value >= 0)
            speed = value;
    }

    public float GetSpeed()
    {
        return speed;
    }
}

SerializeField로 에디터에서는 보이게 하되,
스크립트에서는 private하게 유지하는 것도 일종의 캡슐화야


✅ 캡슐화를 위한 주요 키워드 정리

키워드설명
private 외부 접근 불가, 내부에서만 사용 가능
public 외부 접근 허용
protected 자식 클래스는 접근 가능
internal 같은 어셈블리 내에서는 접근 가능
property (get, set) 안전한 접근 인터페이스 제공

✅ 요약 한 줄

캡슐화는 “객체 내부의 상태를 보호하고, 오직 허용된 방식으로만 외부에 접근하게 만드는 것”이다.

 

 

이 내용 또한 회사 면접에서 나왔던 내용이다 개발할떄 잘만 써놓고 용어를 몰라서... 잘 모르곘다고 대답했었다..ㅋㅋㅋㅋㅋ...바보..앞으로는 절대 그럴 일 없겠다..하하...

반응형
반응형

✅ 박싱(Boxing) & 언박싱(Unboxing)

🔸 박싱(Boxing)

  • 값 형식(Value Type) 데이터를 **참조 형식(Reference Type)**으로 변환하는 것
  • 값 타입(예: int, float)을 object 타입에 저장하면 박싱이 발생
  • 이 과정에서 값이 힙에 복사되고, 새로운 참조 객체로 할당
int num = 10; object obj = num; // 박싱

🔸 언박싱(Unboxing)

  • 박싱된 object를 다시 원래의 값 타입으로 꺼내오는 것
  • 힙에 있는 데이터를 스택에 복사하는 작업
  • 반드시 명시적 형변환이 필요하며, 잘못된 형변환 시 런타임 오류 발생
int original = (int)obj; // 언박싱

🔸 단점

  • 박싱/언박싱은 메모리 할당과 복사 비용이 발생 → 성능 저하
  • 특히 루프, 게임 로직에서 자주 발생하면 GC 부담으로 이어짐

 

그리고 궁금한게 생겼다 그럼 형변환과 무엇이 차이날까? 싶어서 GPT한테 물어보았다.

 

✅ 형변환(casting) vs 박싱/언박싱의 차이

🔹 형변환(casting)

  • 같은 형식 계열 내에서 타입만 바꾸는 것
  • 메모리 위치나 구조는 그대로
 
float f = 3.14f; int i = (int)f; // 형변환 (float → int)

스택 내에서 값 자체가 바뀌는 것이지, 힙에 복사되는 게 아님

 

✅ 꼭 object로 해야 박싱/언박싱이 일어날까?

🔥 박싱은 object뿐만 아니라 인터페이스로도 발생해!

예시:

interface IPrintable
{
    void Print();
}

struct MyStruct : IPrintable
{
    public void Print() { Console.WriteLine("Hello"); }
}

IPrintable p = new MyStruct(); // ✅ 박싱 발생
  • MyStruct는 값 타입이지만, IPrintable은 참조 타입이기 때문에 박싱이 발생함

 

일단 박싱/언박싱은 확실히 힙까지 사용되지만 형변환은 스택 내에서만 일어나는 일이라는걸 알게됐다!!

 

회사 면접볼때 박싱과 언박싱에 대해서 질문이 나왔던 적이 있다. 사실..여태까지는 잘 생각 안하고 사용했다..기초지식이 확실히 중요한거같다 ㅠㅜ 열심히 공부하자..이제 질문나오면 확실히 대답할 수 있다!!!

 

반응형

'C#' 카테고리의 다른 글

C# - .NET Runtime  (1) 2025.07.01
C# - 캡슐화  (1) 2025.07.01
C# Unity - 가비지 컬렉터(GC) 자동실행기준  (1) 2025.07.01
C# 주사위게임  (0) 2023.03.12
C# 칸 이동 게임  (0) 2023.03.12