본문 바로가기
Game DevTip/C#

1. C# 기초

by LIKE IT.라이킷 2025. 4. 21.

 

1. CLR의 타입 시스템

 - CLR : 공통 언어 런타임, 즉 모든 C# 코드의 실행 환경

 - 타입 안정성 : 잘못된 타입 사용방지

 - 모든 타입은 'System.Object'에서 파생됨.

 

2. 값 타입 

 - struct, enum 두가지 형식(값 형식은 sealed)

 - int, long, double, char, bool등,

 - 스택에 할당되며, 값 자체를 저장한다. 

 - 변수간의 복사는 값 자체의 복사이다.

int // System.Int32
long // System.Int64
double // System.Double
int a = 0; // System.Int32 a = new System.Int32();

 

 

 - 변수간 복사는 값자체의 복사이므로, GC 관여없이 효율적이다. 

int a = 10;
int b = a;
b = 20;
Console.WriteLine(a); // 10

 

 

3. 참조타입

 - class, interface, array, delegate등,

 - 힙에 저장되며, 변수는 각 객체의 참조(주소)를 저장한다. 

 - 복사는 참조만 전달하게 된다.

 

class Person { public string Name; }
Person p1 = new Person { Name = "Alice" };
Person p2 = p1;
p2.Name = "Bob";
Console.WriteLine(p1.Name); // "Bob"

 

깊은 복사 예시

class Car {
	public string Model { get; set; }
}

static void Main() {
	Car car1 = new Car { Model = "Toyota" };
	Car car2 = car1; // car1과 같은 객체를 참조 (얕은 복사)
	car2.Model = "Honda"; // car2를 수정하면 car1에도 영향이 있음

	Console.WriteLine(car1.Model); // 출력: Honda
	Console.WriteLine(car2.Model); // 출력: Honda
	Console.WriteLine(object.ReferenceEquals(car1, car2)); // 출력: True (같은 객체 참조)

	// 깊은 복사 예시 (새로운 객체 생성, 문자열은 값 복사됨)
	Car car3 = new Car { Model = car1.Model };
	car3.Model = "Ford"; // car3만 변경, car1은 영향 없음

	Console.WriteLine(car1.Model); // 출력: Honda
	Console.WriteLine(car3.Model); // 출력: Ford
}

 

 

4. 박싱

 - 값 타입을 참조 타입(object)로 변환시킨다. 

 - CLR 동작 : 값이 스택에서 힙으로 이동하며, 새 객체를 생성한다.

int num = 10;
object obj = num; // 박싱

 

 

5. 언박싱

 - 참조타입에서 값 타입으로 변환.

 - CLR 동작 : 타입이 맞지 않으면 invaildCastException이 발생하게 된다. 

* 참고로 박싱과 언박싱은 성은 오버헤드가 발생하므로 주의해야함(메모리 할당 및 GC 부담)

 

int num 2 = (int)obj; // 언박싱

 

InvalidCastException은 잘못된 형 변환(캐스트)을 시도할 때 발생하는 예외입니다.

즉, 호환되지 않는 형식 간의 변환을 수행하려 할 때 발생합니다.


InvalidCastException이 발생하는 경우

부모-자식 관계가 아닌 타입 변환 시

object obj = "Hello";
int num = (int)obj; // ❌ InvalidCastException 발생!

- obj는 문자열이지만, 이를 int로 변환하려고 하면 예외 발생!

클래스 간 잘못된 캐스트

class Animal { }
class Dog : Animal { }
class Cat : Animal { }

static void Main()
{
    Animal a = new Dog();
    Cat c = (Cat)a; // ❌ InvalidCastException 발생!
}

- a는 Dog 타입인데, Cat으로 변환하려 하면 예외 발생.

3️⃣ 인터페이스 구현이 안 된 객체를 인터페이스로 캐스팅

interface ICar { }
class Car { }

static void Main()
{
    Car myCar = new Car();
    ICar carInterface = (ICar)myCar; // ❌ InvalidCastException 발생!
}

  • Car 클래스가 ICar를 구현하지 않았기 때문에 변환 불가.

해결 방법

  1. as 키워드 사용
  2. object obj = "Hello"; string str = obj as string; //
  3. 올바른 변환 (실패하면 null 반환) if (str != null) { Console.WriteLine(str); }
  4. is 키워드로 타입 확인 후 변환
  5. object obj = "Hello"; if (obj is string) { string str = (string)obj; Console.WriteLine(str); }
  6. TryCast(C#에서는 직접 구현 필요)
    • C#에는 TryCast가 없지만, is와 as를 활용하여 예외를 방지할 수 있음.

🔥 결론

InvalidCastException은 잘못된 형 변환을 시도할 때 발생하는 예외이며,

as 키워드 또는 is 키워드로 방지할 수 있음.

 

 

System.Object

  • 모든 타입의 기본 클래스
  • 주요 메서드
    • ToString() : 문자열 표현
    • Equals() : 동등성 비교
    • GetHashCode() : 해시코드
    • GetType() : 런타임 타입정보
int i = 42;
Console.WriteLine(i.GetType()); // System.Int32

 

 

C++ 구조체와 C#의 구조체의 다른점

  • C++
    • 스택 힙 가능.(스택기본)
    • 상속 가능
    • 접근지정자 기본 public
    • 생성자 가능
    • 소멸자 가능
    • 값타입 기본(힙도 가능)
    • 얕은 복사
  • C#
    • 스택 기본 / 힙 직접 할당 불가.
    • 상속 불가능(인터페이스만 가능)
    • 기본 private
    • 생성자 매개변수 있는 생성자는 가능. (없으면 불가능)
    • 소멸자 불가능
    • 값타입 (힙 직접 할당 불가)
    • 깊은 복사(Deep Copy)
using System;

class Q
{
    public string Question { get; set; }  // 문제
    public string Answer { get; set; }    // 정답
    public int Difficulty { get; set; }   // 난이도 (1~3)
}

class Program
{
    static void Main()
    {
        // 퀴즈 데이터 구성 //클래스 배열
        Q[] quizzes = new Q[]
        {
            new Q { Question = "C#에서 정수를 저장하는 데이터 타입은?", Answer = "int", Difficulty = 1 },
            new Q { Question = "2 + 3은 얼마인가?", Answer = "5", Difficulty = 1 },
            new Q { Question = "C#에서 문자열을 나타내는 타입은?", Answer = "string", Difficulty = 2 }
        };

        int totalScore = 0;  // 총 점수
        int totalQuestions = quizzes.Length;  // 퀴즈 개수

	      // foreach로 quizzes 배열을 순차적으로 반복
				foreach (var quiz in quizzes)
				{
				    Console.WriteLine(quiz.Question);  // quiz.Question은 현재 퀴즈의 질문을 출력
					  string userAnswer = Console.ReadLine();  // 사용자로부터 답을 입력받음

            // 정답 확인
            if (userAnswer.Equals(quiz.Answer, StringComparison.OrdinalIgnoreCase))
            {
                int score = quiz.Difficulty * 10;  // 난이도 * 10 점 부여
                totalScore += score;
                Console.WriteLine($"정답입니다! 점수: {score}점");
            }
            else
            {
                Console.WriteLine("틀렸습니다!");
            }
        }

        // 총점과 평균 점수 출력
        double averageScore = (double)totalScore / totalQuestions;
        Console.WriteLine($"\\n총 점수: {totalScore}점");
        Console.WriteLine($"평균 점수: {averageScore:F2}점");
    }
}

  • foreach (var quiz in quizzes)는 C#에서 배열 또는 컬렉션을 순차적으로 반복하는 방법입니다.
  • 이 코드는 quizzes라는 배열이나 리스트에 저장된 각 퀴즈 객체를 하나씩
  • quiz 변수에 할당하면서 반복적으로 실행됩니다.
  • 즉, 배열의 각 요소에 대해 자동으로 하나씩 접근할 수 있게 해주는 구문입니다.

구체적인 설명

  • quizzes: 배열 또는 컬렉션(예: 리스트, 배열 등). 이 코드에서는 Q 객체들이 들어있는 배열입니다.
  • quiz: 배열의 각 요소를 하나씩 참조하는 변수입니다. 여기서는 각 퀴즈를 quiz라는 이름으로 다룰 수 있습니다.
  • var: var는 암시적 타입 추론을 사용하여, quiz의 타입을 자동으로 결정합니다.
  • 여기서는 Q 클래스 객체를 의미합니다.
  • 즉, quizzes 배열 안의 각 항목은 Q 타입의 객체이므로 var를 사용하여 quiz를 Q 타입으로 처리합니다.
반응형

'Game DevTip > C#' 카테고리의 다른 글

4. C# 인터페이스 및 추상클래스 ,다형성  (0) 2025.04.21
3. C# 클래스  (1) 2025.04.21
2. C# 배열, 함수, 델리게이트  (0) 2025.04.21

댓글