[내일배움캠프] 4일차 (25.07.03)

김혜현·2025년 7월 3일
0

내일배움캠프

목록 보기
14/15

- object

https://www.youtube.com/watch?v=a7iHDWiSSm4

  • 모든 데이터를 다룰 수 있는 특별한 자료형

  • object는 참조타입

int a는 값타입이므로 stack에 들어가지만, object a는 heap에 들어간 주소값만을 가지게 된다.
-박싱 (Boxing)
스택 영역 데이터를 힙 영역에 할당하는 것

-언박싱 (UnBoxing)

힙 영역 데이터를 스택 영역에 할당하는 것 (값 형식을 언박싱하면 데이터가 복사되고, 기존의 데이터는 가비지가 됨)

-object 클래스 함수

ToString() : 해당 인스턴스가 속한 전체 이름을 반환 (단 C# 기본 자료형(short, int...)은 해당 타입이 가지고 있는 값을 반환(재정의))

GetType() : 클래스를 선언하면 내부적으로 클래스 정보를 가지고 있는 Type 인스턴스가 생성되는데 이를 가지고 올 수 있는 메서드

Equals() : 값을 비교한 결과를 boolean형으로 반환한다. (동일하면 true, 아니면 false)

GetHashCode() : 특정 인스턴스를 고유하게 식별할 수 있는 4바이트 int 값을 반환 (값 형식에서는 데이터가 같으면 똑같은 값이 나옴)

- C# 1.0 컬렉션 (Collection)

https://www.youtube.com/watch?v=xO8bNLfCSMU
같은 데이터 성격을 가진 데이터 모음을 담는 자료구조

C# 1.0 컬렉션의 공통 특징

모두 object 기반
→ 박싱/언박싱 필요 (성능 저하 원인)
→ 타입 안정성 부족 (캐스팅 오류 가능성 존재)

제네릭 없음
→ 타입별로 클래스를 따로 만들거나, object로 처리해야 했음

-ArrayList

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        // ArrayList 생성
        ArrayList list = new ArrayList();

        // Add: 요소 추가
        list.Add(10);            // int -> object로 박싱
        list.Add("Hello");
        list.Add(3.14);

        // AddRange: 여러 요소 한꺼번에 추가
        list.AddRange(new object[] { 100, "World", true });

        // Insert: 특정 위치에 요소 삽입
        list.Insert(1, "Inserted");

        // Remove: 값으로 요소 제거 (첫 번째 일치 항목)
        list.Remove("Hello");

        // RemoveAt: 인덱스로 요소 제거
        list.RemoveAt(0);

        // Contains: 값 존재 여부 확인
        bool hasWorld = list.Contains("World"); // true

        // IndexOf: 값의 인덱스 확인
        int index = list.IndexOf("World");

        // Count: 현재 요소 개수
        int count = list.Count;

        // Clear: 전체 요소 제거
        list.Clear();

        // 다시 추가 후 출력
        list.Add("One");
        list.Add("Two");
        list.Add("Three");

        // 반복문으로 요소 출력
        foreach (object item in list)
        {
            Console.WriteLine(item);
        }
    }
}
메서드설명
Add(object)요소 추가
AddRange(ICollection)여러 요소 한 번에 추가
Insert(index, object)특정 위치에 요소 삽입
Remove(object)특정 요소 제거
RemoveAt(index)인덱스로 요소 제거
Clear()전체 요소 제거
Contains(object)해당 값 포함 여부 확인
IndexOf(object)값의 인덱스 반환
Count현재 저장된 요소 개수

-Hashtable

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        // Hashtable 생성
        Hashtable ht = new Hashtable();

        // Add: 키-값 쌍 추가
        ht.Add("id", 101);
        ht.Add("name", "Alice");
        ht.Add("isAdmin", true);

        // 인덱서로 값 접근 (키 사용)
        Console.WriteLine(ht["name"]);  // 출력: Alice

        // ContainsKey: 키 존재 여부 확인
        if (ht.ContainsKey("id"))
            Console.WriteLine("ID 있음");

        // Contains: 값 존재 여부 확인
        if (ht.Contains(true))
            Console.WriteLine("true 값 있음");

        // Remove: 특정 키 삭제
        ht.Remove("isAdmin");

        // Count: 총 요소 개수
        Console.WriteLine("총 개수: " + ht.Count);

        // 반복문: 모든 키-값 출력
        foreach (DictionaryEntry entry in ht)
        {
            Console.WriteLine($"{entry.Key} : {entry.Value}");
        }

        // Clear: 모든 요소 제거
        ht.Clear();
    }
}
메서드/속성설명
Add(key, value)키-값 쌍 추가 (키 중복 시 예외 발생)
Remove(key)해당 키 삭제
Clear()전체 요소 제거
ContainsKey(key)특정 키가 있는지 확인
Contains(value)특정 값이 있는지 확인
Count저장된 항목 수
Keys모든 키 컬렉션 반환 (ICollection)
Values모든 값 컬렉션 반환 (ICollection)
this[key]인덱서 접근 (ht["key"] = value; 형태)

-Stack

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        // 1. Stack 생성
        Stack stack = new Stack();

        // 2. Push(object): 요소 추가
        stack.Push("Apple");
        stack.Push("Banana");
        stack.Push("Cherry");

        // 현재 스택: Top -> Cherry, Banana, Apple

        // 3. Peek(): 맨 위 요소 확인 (제거하지 않음)
        Console.WriteLine("Top: " + stack.Peek());  // Cherry

        // 4. Pop(): 맨 위 요소 제거 + 반환
        Console.WriteLine("Pop: " + stack.Pop());   // Cherry 제거
        Console.WriteLine("Pop: " + stack.Pop());   // Banana 제거

        // 5. Contains(value): 특정 값 포함 여부
        bool hasApple = stack.Contains("Apple");    // true
        Console.WriteLine("Contains Apple: " + hasApple);

        // 6. Count: 요소 개수
        Console.WriteLine("Count: " + stack.Count); // 1

        // 7. Clear(): 모든 요소 제거
        stack.Clear();
        Console.WriteLine("지운 후 Count: " + stack.Count); // 0
    }
}
메서드 / 속성설명
Push(object)요소 추가 (위에 쌓음)
Pop()맨 위 요소 제거 + 반환
Peek()맨 위 요소 확인 (제거는 안 함)
Contains(object)값 포함 여부 확인
Clear()전체 요소 제거
Count현재 저장된 요소 개수
ToArray()배열로 변환 (스택 순서 유지됨)

-Queue

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        // 1. Queue 생성
        Queue queue = new Queue();

        // 2. Enqueue(object): 요소 추가
        queue.Enqueue("A");
        queue.Enqueue("B");
        queue.Enqueue("C");

        // 현재 큐: Front -> A, B, C

        // 3. Peek(): 맨 앞 요소 확인 (제거 X)
        Console.WriteLine("Peek: " + queue.Peek()); // A

        // 4. Dequeue(): 맨 앞 요소 제거 + 반환
        Console.WriteLine("Dequeue: " + queue.Dequeue()); // A 제거
        Console.WriteLine("Dequeue: " + queue.Dequeue()); // B 제거

        // 5. Contains(value): 값 포함 여부
        Console.WriteLine("Contains C? " + queue.Contains("C")); // true

        // 6. Count: 남은 요소 개수
        Console.WriteLine("Count: " + queue.Count); // 1

        // 7. Clear(): 모든 요소 제거
        queue.Clear();
        Console.WriteLine("지운 후 Count: " + queue.Count); // 0
    }
}
메서드 / 속성설명
Enqueue(object)요소를 큐의 뒤에 추가
Dequeue()앞쪽 요소를 제거하고 반환
Peek()앞쪽 요소 확인 (제거 X)
Contains(object)특정 값이 있는지 확인
Clear()모든 요소 제거
Count현재 요소 수
ToArray()큐를 배열로 변환 (순서 유지됨)

- C# 2.0 제네릭 (Generic)

https://www.youtube.com/watch?v=gQvTCxcyt_k

  • 여러 자료형에 대해 하나의 클래스나 메서드를 재사용할 수 있도록 하는 기능
  • 컴파일 시점에 타입을 지정해서, 형변환 없이 타입 안정성 확보 + 성능 향상
  • 형식 매개변수
    제네릭의 자료형을 나타냄
public class Box<T>  // T: 형식 매개변수
{
    public T Value;
}
  • 제약 조건
    형식 매개변수에 넣을 수 있는 타입을 제한하는 기능
public class Factory<T> where T : new()
{
    public T Create() => new T();
}

제약 조건의미
where T : class참조 타입만 허용
where T : struct값 타입만 허용
where T : new()매개변수 없는 생성자 필요
where T : BaseClass특정 클래스 또는 인터페이스 상속 필요
where T : interface특정 인터페이스 구현 필요
where T : unmanaged비관리형 타입만 가능 (C# 7.3+)
  • 기본값 할당 (default(T))
    제네릭에서는 타입을 알 수 없기 때문에, 초기화하려면 default 키워드를 사용
public class Box<T>
{
    public T value = default(T);  // T가 int면 0, string이면 null
}

- 기초문법 마무리

https://www.youtube.com/watch?v=MPmAKNwOHus

- 기본 문법 용어

✅ 1. 예약어 (Keyword)
📌 정의
C# 언어 자체에서 미리 정해진 단어들로, 특별한 의미와 기능을 가진 언어 구성 요소

📌 특징

  • 변수나 메서드 이름 등으로 사용 불가능
  • 컴파일러가 특정 문법을 이해할 때 사용하는 고정된 키워드

📌 예시

int, class, public, if, while, return, using, void, static, new

🔒 예시 코드 (불가능한 경우)

int if = 5;  // ❌ 오류: 예약어는 변수 이름으로 사용할 수 없음

✅ 2. 식별자 (Identifier)
📌 정의
개발자가 직접 정의하는 이름
변수, 함수, 클래스, 메서드, 속성, 객체 등의 이름에 사용됨

📌 특징

  • 첫 글자는 문자나 밑줄(_)로 시작
  • 숫자는 두 번째 글자부터 사용 가능
  • 예약어는 사용할 수 없음
  • 대소문자 구분함 (myVar ≠ MyVar)

📌 예시

int age = 20;      // age: 식별자
string name = "Tom";  // name: 식별자

✅ 3. 리터럴 (Literal)
📌 정의
고정된 값 자체를 의미. 코드 안에서 변수에 대입되는 실제 데이터

📌 특징

  • 값 자체를 의미 (변수 아님)
  • 문자열, 숫자, 불리언, 문자 등 여러 타입이 있음

📌 예시

리터럴 종류예시
정수 리터럴100, -5
실수 리터럴3.14, -0.01f
문자 리터럴'A', '9'
문자열 리터럴"Hello", ""
불리언 리터럴true, false
int num = 100;        // 100이 리터럴
string s = "hello";   // "hello"가 리터럴

✅ 4. 상수 (Constant)
📌 정의
한 번 정해지면 바뀌지 않는 값
값을 저장하되, 변경 불가. 프로그램 내에서 의미 있는 이름을 부여해 사용

📌 특징

  • const 키워드 사용
  • 컴파일 타임에 값이 결정되어야 함
  • 일반적으로 대문자와 밑줄로 표기 (MAX_SIZE, PI)

📌 예시

const double PI = 3.14159;
const int MAX_COUNT = 100;

🎯 요약 비교표

구분의미예시
예약어언어에서 정해둔 키워드int, class, return
식별자프로그래머가 정한 이름age, score, Print()
리터럴코드에 적힌 고정된 실제 값100, "hello", true
상수값이 변하지 않는 변수const int LIMIT = 10

- 다차원 배열

✅ 1. 1차원 배열

int[] arr = new int[5] { 1, 2, 3, 4, 5 };

✅ 2. 2차원 배열

int[,] arr2 = new int[4, 5]
{
    { 1, 2, 3, 4, 5 },     // 0행
    { 6, 7, 8, 9, 10 },    // 1행
    { 11,12,13,14,15 },    // 2행
    { 16,17,18,19,20 }     // 3행
};

[4, 5]: 4행 5열 배열 (총 20칸)

✅ 3. 3차원 배열

int[,,] arr3 = new int[3, 4, 5]
{
    {
        { 1, 2, 3, 4, 5 },
        { 6, 7, 8, 9, 10 },
        { 11,12,13,14,15 },
        { 16,17,18,19,20 }
    },
    {
        { 1, 2, 3, 4, 5 },
        { 6, 7, 8, 9, 10 },
        { 11,12,13,14,15 },
        { 16,17,18,19,20 }
    },
    {
        { 1, 2, 3, 4, 5 },
        { 6, 7, 8, 9, 10 },
        { 11,12,13,14,15 },
        { 16,17,18,19,20 }
    }
};

[3, 4, 5]:
1차원: 깊이(층) → 3개
2차원: 행 → 4개
3차원: 열 → 5개
총 원소 개수 = 3 × 4 × 5 = 60

📦 접근 예시

arr3[0, 0, 0] = 1;     // 1층 1행 1열
arr3[2, 3, 4] = 20;    // 3층 4행 5열

- 삼항 연산자

✅ 삼항 연산자란?
삼항 연산자는 조건에 따라 두 값 중 하나를 선택할 수 있는 간단한 조건문 표현 방식.

조건 ? 참일 때의 값 : 거짓일 때의 값;

✅ 예시

int age = 18;
string result = (age >= 19) ? "성인" : "미성년자";

age >= 19 조건이 거짓이므로 "미성년자"가 선택됨.

✅ if문과의 비교

// if문 사용
if (score >= 60)
    result = "합격";
else
    result = "불합격";

// 삼항 연산자 사용
result = (score >= 60) ? "합격" : "불합격";

결과는 같지만, 삼항 연산자는 코드를 간결하게 만듬.

- goto문

  • 지정한 레이블(label) 위치로 흐름을 즉시 이동.
  • 일반적인 상황에서는 잘 사용되지 않으며, 가독성과 유지보수를 어렵게 만들 수 있기 때문에 필요할 때만 신중하게 사용하는 것이 권장됨.
goto 레이블이름;
...
레이블이름:
    실행할 코드;

✅ 예시
goto는 break, continue, return으로 해결하기 어려운 흐름 제어가 필요할 때, 예외적으로 사용할 수 있음.

for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        if (i == 2 && j == 3)
            goto EndLoop;
        Console.WriteLine($"i={i}, j={j}");
    }
}

EndLoop:
Console.WriteLine("이중 반복문 강제 종료됨"); 

- goto case / goto default

✅ goto case / goto default란?

  • switch 문 안에서 다른 case로 흐름을 이동할 수 있게 해주는 goto.
  • 일반 goto와는 다르게, 안전하고 허용된 형태로 자주 사용됨.

✅ 예시: goto case

int number = 2;

switch (number)
{
    case 1:
        Console.WriteLine("1번입니다.");
        break;
    case 2:
        Console.WriteLine("2번입니다. → 3번으로 이동");
        goto case 3;  // case 3으로 흐름 이동
    case 3:
        Console.WriteLine("3번입니다.");
        break;
    default:
        Console.WriteLine("기본값입니다.");
        break;
}

📌 출력:
2번입니다. → 3번으로 이동
3번입니다.

✅ 예시: goto default

string input = "hello";

switch (input)
{
    case "hi":
        Console.WriteLine("안녕하세요");
        break;
    case "bye":
        Console.WriteLine("잘 가요");
        break;
    default:
        Console.WriteLine("기본 인사입니다.");
        break;
    case "hello":
        Console.WriteLine("hello입니다. → default로 이동");
        goto default;
}

📌 출력:

hello입니다. → default로 이동  
기본 인사입니다.

✅ 요약 정리

구문의미
goto case n;지정된 case로 이동
goto default;default 블록으로 이동
switch 내에서만 사용 가능일반 코드에서는 사용 불가

- 객체지향

https://www.youtube.com/watch?v=HOfoNakTyQM

- 객체지향 (Object-Oriented Programming, OOP)

현실 세계를 객체라는 단위로 나누고, 이 객체들끼리 상호작용하게 만들어서 프로그램을 구성하는 방식.

특징설명예시
캡슐화데이터와 기능을 하나로 묶고, 외부에서 직접 접근 못하게 보호private 필드, public 메서드로만 접근
상속기존 클래스의 기능을 물려받고 확장class Dog : Animal
다형성같은 함수 호출이 객체에 따라 다르게 동작virtual / override, 인터페이스
추상화불필요한 세부사항은 감추고 중요한 것만 드러냄인터페이스, 추상 클래스

- 클래스 (Class)

객체를 만들기 위한 설계도.
속성(변수) + 기능(메서드)을 정의한 구조체.

📦 클래스 구조 예시

public class Player {
    // 필드(속성)
    public string name;
    private int hp;

    // 생성자
    public Player(string name, int hp) {
        this.name = name;
        this.hp = hp;
    }

    // 메서드(기능)
    public void TakeDamage(int damage) {
        hp -= damage;
        Console.WriteLine($"{name}이(가) {damage}만큼 피해를 입음 (HP: {hp})");
    }
}

🎮 객체(Object) 생성 예시

Player p1 = new Player("용사", 100);
p1.TakeDamage(10); // 출력: 용사이(가) 10만큼 피해를 입음 (HP: 90)

- 생성자

객체가 생성될 때 자동으로 호출되는 특수한 메서드
주로 초기값 설정에 사용됨

📦 기본 형태

public class Player
{
    public string name;
    public int hp;

    // 생성자
    public Player(string name, int hp)
    {
        this.name = name;
        this.hp = hp;
    }
}

// 생성자 호출 예시 (객체 생성)
Player p1 = new Player("용사", 100);

- 생성자 오버로딩

public class Enemy
{
    public int hp;

    // 기본 생성자
    public Enemy() {
        hp = 100;
    }

    // 오버로딩된 생성자
    public Enemy(int hp) {
        this.hp = hp;
    }
}

Enemy e1 = new Enemy();     // hp = 100
Enemy e2 = new Enemy(250);  // hp = 250

- 기본 생성자란

  • 매개변수가 없는 생성자
  • 클래스에 아무 생성자도 안 만들면 컴파일러가 자동으로 기본 생성자 만들어줌
  • 사용자 정의 생성자를 하나라도 만들면, 컴파일러는 기본 생성자를 자동으로 안 만들어줌.
public class Monster {
    public int hp = 100;
}

Monster m = new Monster(); // 기본 생성자 자동 호출

- this() 생성자

자기 자신의 다른 생성자를 호출할 때 사용하는 문법
즉, 같은 클래스 안에서 중복 코드 줄이기 위해 씀

  • 문법
public 클래스이름(매개변수) : this(다른 생성자의 매개변수) { }
  • 예시
public class Enemy
{
    public string name;
    public int hp;

    // 생성자 1
    public Enemy(string name, int hp)
    {
        this.name = name;
        this.hp = hp;
    }

    // 생성자 2 (체력 기본값은 100)
    public Enemy(string name) : this(name, 100) { }

    // 생성자 3 (이름도 기본값, 체력도 기본값)
    public Enemy() : this("이름없음", 100) { }
}

Enemy e1 = new Enemy();             // 이름없음, 100
Enemy e2 = new Enemy("좀비");       // 좀비, 100
Enemy e3 = new Enemy("보스", 300);  // 보스, 300

- 종류자

객체가 소멸될 때 호출되는 메서드
주로 리소스 해제(파일, 핸들, 메모리 등)할 때 사용

🔧 기본 문법

~클래스이름() {
    // 정리할 작업
}
  • 이름 앞에 ~ 붙여서 선언
  • 매개변수 없음, 오버로딩 불가능
  • 직접 호출 불가, GC(Garbage Collector)가 호출함

✅ 예시

public class Monster
{
    public Monster() {
        Console.WriteLine("몬스터 생성됨");
    }

    ~Monster() {
        Console.WriteLine("몬스터 제거됨"); // 종료자
    }
}

Monster m = new Monster(); // 생성자 실행
m = null;                  // 객체 참조 제거
GC.Collect();              // GC 수동 호출 → 종료자 실행될 수 있음
  • 종료자 vs Dispose()
항목종료자 (~Class)Dispose()
호출 주체GC가 자동 호출사용자가 명시적으로 호출
제어 가능성없음있음
사용 대상드물게 사용리소스 관리 시 주로 사용
추천 여부❌ 가급적 피함✅ 강력 추천

예시: IDisposable 사용 권장

public class FileHandler : IDisposable
{
    private FileStream stream;

    public FileHandler(string path)
    {
        stream = new FileStream(path, FileMode.Open);
    }

    public void Dispose()
    {
        stream.Close();
        Console.WriteLine("파일 닫힘");
    }
}

- MonoBehaviour

  • Unity에서 게임 오브젝트에 부착할 수 있는 스크립트 컴포넌트를 만들기 위한 기본 클래스.
  • 게임 오브젝트에 부착한 순간 인스턴스를 생성하여 객체가 되기에 new() 통해 객체를 생성하는 것이 불가능 (그렇기에 초기화는 생성자 대신 아닌 Awake나 Start 사용)
profile
클라이언트 개발자 지망생

0개의 댓글