no image
C# - 자료형과 변수의 기초 — 선언, 리터럴, 코드 스타일
📘 자료형과 변수의 기초 — 선언, 리터럴, 코드 스타일🧩 C# 기본 자료형 개념C#은 자료형에 대해 엄격한 형식 시스템을 가진 언어로, 모든 변수는 선언 시 반드시 자료형을 명시해야 한다.자료형은 메모리의 크기, 표현 범위, 부호 여부에 따라 구분되며, 변수의 용도와 저장할 값의 형태에 따라 적절한 자료형을 선택해야 한다.주요 기본 자료형자료형크기(byte)설명sbyte1-128 ~ 127byte10 ~ 255short2-32,768 ~ 32,767int4-2,147,483,648 ~ 2,147,483,647long8매우 큰 정수float4소수점 표현, 7자리 정확도double8소수점 표현, 15~16자리 정확도decimal16고정 소수점, 금융 계산용char2유니코드 문자 1개 저장string가변..
2025.07.07
C#
no image
C# - C# 기본 구조 완전 정복: 출력, 주석, 자동완성
📘 C# 기본 구조 완전 정복 — 출력, 주석, 자동완성🧩 C# 코드 구조 이해하기C# 프로그램은 반드시 클래스와 메서드로 구성되며, 진입점인 Main 메서드에서 실행이 시작된다.기본 콘솔 애플리케이션 구조는 다음과 같다.using System;namespace HelloWorld{ class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } }}구성 요소 설명using System;: 콘솔 입출력을 포함한 .NET 기본 기능이 정의된 네임스페이스를 포함한다.namespace HelloWorld: 코드의 논리적 구역을 정의하고, 클래스..
2025.07.07
C#
no image
C# - C#과 .NET의 시작, 개발 환경 구축과 Hello World
📘 챕터 1. C# 소개와 개발 환경 설정🧩 C# 언어의 개요C#은 마이크로소프트에서 개발한 객체지향 프로그래밍 언어이다.형식에 엄격하며, 안전성과 효율성을 고려한 구조를 갖추고 있다.C, C++, Java와 유사한 문법을 기반으로 하며, 다양한 플랫폼에서 실행 가능하다.주요 특징객체지향 설계: 모든 구성 요소가 클래스와 객체 기반으로 이루어진다.강한 형식 시스템: 자료형을 명확히 선언해야 하며, 컴파일 타임에 오류를 방지할 수 있다.가비지 컬렉션 지원: 메모리 해제를 자동으로 처리한다.플랫폼 독립성: .NET 플랫폼을 기반으로 다양한 환경에서 실행 가능하다.🛠️ .NET 프레임워크.NET은 C# 프로그램이 실행되는 기반 플랫폼이다.C#으로 작성된 코드는 중간 언어(IL)로 먼저 컴파일되며, 실행 ..
2025.07.07
C#
no image
C# - Adpater Pattern2 C# 코드예제
❓ 어댑터 패턴에대한 이해도가 부족한거 같아서 다시 GPT에게 물어봐서 다시 공부해봤다. namespace로 Adpater를 정의해야 하는 줄 알았는데 그렇지 않았다. 결론은 🎯 결론C#에서 어댑터 패턴은 "직접 클래스와 인터페이스로 구현"하는 것이지, 키워드나 특별한 기능이 있는 건 아니야. ✅오..이건 굉장히 새로운 지식이였다 그냥 클래스와 인터페이스로 구현하는거지 딱히 키워드가 있는게 아니였다새로운사실! 그래서 한 번 예제 코드로 보겠다!INewAttack.cspublic interface INewAttack{ void DoAttack();} IOldAttack.cspublic interface IOldAttack{ void SlashAttack();} OldSwordAttack.csp..
2025.07.06
C#
no image
DesignPattern - Adapter Pattern(어댑터 패턴) + 예제
✅ 어댑터 패턴이란?서로 다른 인터페이스를 가진 두 클래스가 함께 동작하도록 중간에 "변환기" 역할을 해주는 패턴📌 한 줄 요약:"호환되지 않는 인터페이스를 연결해주는 중간 어댑터 클래스"✅ 언제 쓰일까?기존 코드 or 라이브러리 인터페이스를 바꾸지 않고 사용하고 싶을 때인터페이스 불일치 때문에 직접 호출이 안 될 때예전 코드와 새로운 코드를 자연스럽게 연결하고 싶을 때✅ 예제 시나리오: 충전기 어댑터한국 콘센트는 220V미국 전자제품은 110V어댑터를 끼우면 한국 콘센트에 미국 기기를 연결할 수 있어!✅ C# 코드 예제1️⃣ 기존 시스템 (한국 방식)interface ITarget{ void Request(); // 우리가 원하는 방식}class KoreanCharger : ITarget{ ..
2025.07.04
no image
C# - goto
✅ goto란?goto는 프로그램의 흐름을 특정 위치(레이블)로 "강제로" 이동시키는 문법이야.goto 레이블이름;...레이블이름: 실행할 코드;✅ 아주 단순히 말하면:"코드 중간 어딘가로 점프!"✅ 간단한 예제int i = 0;start:Console.WriteLine(i);i++;if (i 🟰 위 코드는 사실상 while문처럼 동작해.✅ goto는 언제 쓰나?switch문에서 중첩된 case 건너뛸 때에러 발생 시 빠르게 특정 cleanup으로 이동매우 드물게 복잡한 상태 머신 구조✅ switch문에서의 goto int num = 2;switch (num){ case 1: Console.WriteLine("One"); break; case 2: ..
2025.07.04
C#
no image
C# - Delegate(델리게이트) + Lambda operator(람다 연산자) + Lambda(람다식)
✅ 델리게이트(Delegate)란?📌 델리게이트는 메서드를 참조할 수 있는 타입이다.쉽게 말하면, **"함수를 변수처럼 다루기 위한 문법"**이야.C#에서 함수 자체는 변수에 담을 수 없지만,델리게이트를 통해 **함수(메서드)를 가리키는 참조(주소)**를 저장하고 호출할 수 있어.✅ 왜 쓸까?델리게이트는 다음과 같은 상황에서 유용해:콜백 함수 구현이벤트(Event) 처리전략(Strategy) 패턴처럼 동작의 유연한 교체다형성 없이 다양한 함수 호출 처리✅ 델리게이트 기본 선언 및 사용// 1. 델리게이트 선언delegate void PrintDelegate(string message);// 2. 사용할 메서드void PrintHello(string msg){ Console.WriteLine("He..
2025.07.04
C#
no image
C# - Queue(큐) vs Stack(스택) + 메모리구조
✅ 핵심 차이 한 줄 요약자료구조개념큐(Queue)FIFO: 먼저 들어간 게 먼저 나온다 (First-In First-Out)스택(Stack)LIFO: 나중에 들어간 게 먼저 나온다 (Last-In First-Out)✅ 실생활 비유자료구조비유 예시Queue줄 서기, 은행 번호표, 프린터 대기열Stack책 쌓기, 접시 쌓기, 웹 브라우저 뒤로가기✅ C# 예제 코드📌 QueueQueue q = new Queue();q.Enqueue("철수");q.Enqueue("영희");Console.WriteLine(q.Dequeue()); // 철수Enqueue() : 데이터 넣기Dequeue() : 가장 먼저 들어온 데이터 꺼내기📌 StackStack s = new Stack();s.Push("철수");s.Push..
2025.07.04
C#
반응형

📘 자료형과 변수의 기초 — 선언, 리터럴, 코드 스타일


🧩 C# 기본 자료형 개념

C#은 자료형에 대해 엄격한 형식 시스템을 가진 언어로, 모든 변수는 선언 시 반드시 자료형을 명시해야 한다.
자료형은 메모리의 크기, 표현 범위, 부호 여부에 따라 구분되며, 변수의 용도와 저장할 값의 형태에 따라 적절한 자료형을 선택해야 한다.

주요 기본 자료형

자료형 크기(byte) 설명
sbyte 1 -128 ~ 127
byte 1 0 ~ 255
short 2 -32,768 ~ 32,767
int 4 -2,147,483,648 ~ 2,147,483,647
long 8 매우 큰 정수
float 4 소수점 표현, 7자리 정확도
double 8 소수점 표현, 15~16자리 정확도
decimal 16 고정 소수점, 금융 계산용
char 2 유니코드 문자 1개 저장
string 가변 유니코드 문자열
bool 1 true / false 논리값
 

자료형 선택 기준

  • 메모리 절약이 필요하면 작은 자료형을 사용한다.
  • 정밀한 소수 표현이 필요하면 double, 금융 계산에는 decimal을 사용한다.
  • 논리 판단에는 반드시 bool을 사용한다.

🧮 리터럴의 개념과 종류

리터럴은 코드 안에 직접 작성된 고정값을 의미한다. 변수에 할당하거나 연산에 사용된다.

대표적인 리터럴 종류

  • 정수형 리터럴: 10, 0x10 (16진수), 0b1010 (2진수)
  • 부동소수점 리터럴: 3.14, 3.14f, 3.14m
  • 문자형 리터럴: 'A', '\n', '\u0022'
  • 문자열 리터럴: "Hello", "이름: \"홍길동\""
  • 논리형 리터럴: true, false

예시:

int age = 25;
float pi = 3.14f;
char grade = 'A';
string name = "Kero";
bool isActive = true;

💡 변수 선언과 초기화

변수는 데이터를 저장할 공간으로, 사용할 자료형에 따라 선언하며 값을 할당할 수 있다.

선언 방법

자료형 변수이름;
int score;

초기화 방법

score = 100;
int health = 50;

여러 개 동시 선언

int x = 1, y = 2, z = 3;

잘못된 예시

int a, b, c = 10; // b는 초기화되지 않음

🧾 식별자와 변수명 규칙

식별자는 변수, 메서드, 클래스 등 모든 이름에 사용되며 아래와 같은 규칙을 따라야 한다.

작성 규칙

  • 영문자 또는 _로 시작해야 한다.
  • 숫자를 처음에 사용할 수 없다.
  • 특수문자(예: -, $)는 사용할 수 없다.
  • 대소문자를 구분한다.
  • C#의 키워드(int, class, public 등)는 사용할 수 없다.

좋은 변수명 예시

int playerScore;
float itemPrice;
string userName;

나쁜 변수명 예시

int x1;     // 의미 없음
string a;   // 모호함
int 1stNum; // 숫자로 시작 → 오류

📐 C# 코드 컨벤션 (이름짓기 스타일)

C#은 표준적인 코드 스타일 가이드라인을 따르며, 대표적으로 PascalCasecamelCase 표기법을 사용한다.

컨벤션 종류

  • PascalCase: 클래스, 메서드, 프로퍼티 등 (PlayerScore, GetItemName)
  • camelCase: 변수, 매개변수 등 (playerScore, itemCount)
  • 대문자 약어: ID, URL 등은 그대로 대문자로 유지한다.

기타 규칙

  • 들여쓰기는 공백 4칸 또는 탭 1칸을 사용한다.
  • 중괄호는 항상 새로운 줄에서 시작한다.
  • 관련 없는 코드 블록은 빈 줄로 구분한다.
  • 메서드 사이에는 1~2줄 간격을 두어 시각적으로 분리한다.

📣 학습 태도와 조언

변수와 자료형은 C#의 기초이자 모든 코드의 출발점이다.
자료형의 크기, 표현 범위, 정수와 실수의 차이를 명확히 이해하고, 의미 있는 변수명을 짓는 연습을 반복하는 것이 중요하다.
또한 C#의 코드 스타일을 일찍부터 습관화하면 협업과 유지보수에 큰 도움이 된다.

반응형
반응형

📘 C# 기본 구조 완전 정복 — 출력, 주석, 자동완성


🧩 C# 코드 구조 이해하기

C# 프로그램은 반드시 클래스와 메서드로 구성되며, 진입점인 Main 메서드에서 실행이 시작된다.
기본 콘솔 애플리케이션 구조는 다음과 같다.

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

구성 요소 설명

  • using System;: 콘솔 입출력을 포함한 .NET 기본 기능이 정의된 네임스페이스를 포함한다.
  • namespace HelloWorld: 코드의 논리적 구역을 정의하고, 클래스 이름 충돌을 방지한다.
  • class Program: 실행 코드가 포함되는 클래스이며, C#에서는 반드시 클래스 또는 구조체 내부에 코드가 존재해야 한다.
  • static void Main(string[] args): 프로그램의 진입점이며, C# 콘솔 애플리케이션에서 반드시 필요한 메서드이다.
  • Console.WriteLine(...): 문자열을 콘솔에 출력하고 줄바꿈을 포함한다.

🖨️ 출력 메서드: Write vs WriteLine

Console.WriteLine()은 문자열 출력 후 줄바꿈까지 처리한다.
Console.Write()는 줄바꿈 없이 출력하며, 다음 출력이 같은 줄에 이어진다.

예를 들어,

Console.Write("A");
Console.Write("B");

는 AB로 출력되며,

Console.WriteLine("A");
Console.WriteLine("B");

는 줄을 바꿔 A와 B가 각각 출력된다.


🔡 이스케이프 시퀀스

이스케이프 시퀀스는 문자열 내부에 특수한 동작을 삽입하기 위해 사용된다.

시퀀스 설명
\n 줄바꿈
\t 수평 탭
\\ 백슬래시 출력
\" 큰따옴표 출력
\' 작은따옴표 출력
 

예시:

Console.WriteLine("이름\t나이");
Console.WriteLine("Kero\t30");

→ 탭 정렬된 표처럼 출력된다.


💬 주석(Comment)

주석은 코드의 설명, 메모, 기록을 위한 도구로, 컴파일러에 의해 무시된다.

  • 한 줄 주석: //를 사용하며 해당 줄 끝까지 주석 처리된다.
  • 여러 줄 주석: /* */를 사용하며 시작과 끝을 명시해 범위 주석을 작성한다.

좋은 주석은 다음을 만족해야 한다.

  • 정확한 설명을 담고 있어야 한다.
  • 오래된 정보가 포함되어 있지 않아야 한다.
  • 코드의 흐름이나 의도를 명확히 드러내야 한다.

주석은 코드 자체를 대체하지 않고 보완하는 수단이어야 하며, 필요할 때만 작성하는 것이 바람직하다.


⚙️ 자동완성과 코드 템플릿 기능

Visual Studio는 개발자의 코딩 생산성을 높이기 위해 자동완성 기능을 지원한다.

  • Tab 키를 이용해 변수명, 클래스명, 메서드명 등을 자동완성할 수 있다.
  • Ctrl + Space를 누르면 사용 가능한 메서드 목록과 설명이 표시된다.
  • 반복문, 조건문 등의 구조를 작성할 때 for, if 입력 후 Tab을 두 번 누르면 코드 템플릿이 자동으로 생성된다.

이 기능은 코드를 빠르게 작성할 수 있도록 도와주며, 오타로 인한 오류를 줄여준다.


📣 학습 태도와 조언

문법이나 키워드를 외우기보다 코드 구조의 원리를 이해하는 것이 우선되어야 한다.
특히 namespace, class, Main 메서드의 관계와 역할을 정확히 파악하는 것이 중요하다.
직접 입력하고 실행해보는 경험을 통해 출력 방식, 주석 처리, 자동완성 기능 등을 체득하는 것이 효과적인 학습 방법이다.

반응형
반응형

📘 챕터 1. C# 소개와 개발 환경 설정


🧩 C# 언어의 개요

C#은 마이크로소프트에서 개발한 객체지향 프로그래밍 언어이다.
형식에 엄격하며, 안전성과 효율성을 고려한 구조를 갖추고 있다.
C, C++, Java와 유사한 문법을 기반으로 하며, 다양한 플랫폼에서 실행 가능하다.

주요 특징

  • 객체지향 설계: 모든 구성 요소가 클래스와 객체 기반으로 이루어진다.
  • 강한 형식 시스템: 자료형을 명확히 선언해야 하며, 컴파일 타임에 오류를 방지할 수 있다.
  • 가비지 컬렉션 지원: 메모리 해제를 자동으로 처리한다.
  • 플랫폼 독립성: .NET 플랫폼을 기반으로 다양한 환경에서 실행 가능하다.

🛠️ .NET 프레임워크

.NET은 C# 프로그램이 실행되는 기반 플랫폼이다.
C#으로 작성된 코드는 중간 언어(IL)로 먼저 컴파일되며, 실행 시점에 CLR(Common Language Runtime)이 이를 기계어로 변환하여 실행한다.
이 과정에서 메모리 관리, 예외 처리, 보안 등의 기능을 자동으로 제공받을 수 있다.


💻 Visual Studio 설치 및 프로젝트 생성

Visual Studio는 C# 개발에 가장 널리 사용되는 통합 개발 환경(IDE)이다.

설치 절차

  • Visual Studio 공식 홈페이지에서 설치 파일을 다운로드한다.
  • 설치 시 .NET 데스크톱 개발 워크로드를 선택한다.
  • 설치 완료 후 초기 설정을 진행한다.

콘솔 앱 생성 방법

  • Visual Studio 실행 → 새 프로젝트 만들기
  • C# 콘솔 앱 선택
  • .NET 6.0 선택 + 최상위 문 사용 안함 설정
  • 프로젝트 이름 및 경로 설정 후 생성

🖨️ Hello World 출력하기

아래는 C#으로 작성한 가장 기본적인 콘솔 출력 프로그램이다.

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

구성 요소 설명

  • using System;: Console 클래스 등 기본 기능을 사용하기 위한 선언이다.
  • namespace HelloWorld: 코드 영역을 구분하는 논리적 단위이다.
  • class Program: 실행 로직을 담는 클래스이다.
  • static void Main(string[] args): 프로그램의 진입점이다.
  • Console.WriteLine(...): 콘솔에 문자열을 출력하고 줄바꿈을 포함한다.

⚙️ 자동완성과 보조 기능

Visual Studio는 IntelliSense라는 자동완성 기능과 코드 템플릿 기능을 지원한다.

자동완성

  • Tab 키를 사용해 클래스명이나 메서드명을 자동으로 완성할 수 있다.
  • Ctrl + Space를 누르면 사용 가능한 메서드 목록, 설명, 인자 정보를 확인할 수 있다.

코드 템플릿

  • for, if, while 등 키워드 입력 후 Tab을 두 번 누르면 기본 구조가 자동 생성된다.

📣 강의에서의 학습 태도와 조언

무엇을 배우는가보다 왜 배우는가에 집중해야 한다.
문법을 단순히 외우기보다는 그 목적과 맥락을 이해하는 것이 장기적인 실력으로 이어진다.

또한, 완벽한 코드를 한 번에 작성하는 것보다 빠르게 시도하고 실패하면서 수정하는 경험이 중요하다.
많이 써보고, 직접 에러를 겪고 해결하면서 성장할 수 있다.

 

사실 기초는 이미 알고있지만 다시 상기 시킨다는 목적으로 하나씩 다시 공부해봐야겠다. 개발자는 겸손할 수 밖에 없는 직업이기 때문에 항상 겸손하자..

반응형
반응형

어댑터 패턴에대한 이해도가 부족한거 같아서 다시 GPT에게 물어봐서 다시 공부해봤다. namespace로 Adpater를 정의해야

하는 줄 알았는데 그렇지 않았다. 결론은 

🎯 결론

C#에서 어댑터 패턴은 "직접 클래스와 인터페이스로 구현"하는 것이지, 키워드나 특별한 기능이 있는 건 아니야.

 

오..이건 굉장히 새로운 지식이였다 그냥 클래스와 인터페이스로 구현하는거지 딱히 키워드가 있는게 아니였다

새로운사실! 그래서 한 번 예제 코드로 보겠다!

INewAttack.cs

public interface INewAttack
{
    void DoAttack();
}

 

IOldAttack.cs

public interface IOldAttack
{
    void SlashAttack();
}

 

OldSwordAttack.cs

public class OldSwordAttack : IOldAttack
{
    public void SlashAttack()
    {
        Console.WriteLine("Old sword slashes the enemy!");
    }
}

 

OldSwordAdapter.cs

public class OldSwordAdapter : INewAttack
{
    private readonly IOldAttack _oldAttack;

    public OldSwordAdapter(IOldAttack oldAttack)
    {
        _oldAttack = oldAttack;
    }

    public void DoAttack()
    {
        // 새 인터페이스를 통해 기존 메서드를 호출
        _oldAttack.SlashAttack();
    }
}

 

Program.cs

using System;

class Program
{
    static void Main(string[] args)
    {
        // 레거시 시스템
        IOldAttack oldAttack = new OldSwordAttack();

        // 어댑터를 통해 새 시스템에 연결
        INewAttack adaptedAttack = new OldSwordAdapter(oldAttack);

        // 새 시스템의 인터페이스 사용
        adaptedAttack.DoAttack();
    }
}

💡 요약

  • INewAttack: 새 클라이언트 인터페이스
  • IOldAttack + OldSwordAttack: 레거시 시스템
  • OldSwordAdapter: 어댑터 클래스
  • Program.cs: 어댑터를 통해 새 방식으로 레거시 클래스를 사용하는 예

처음에는 이해가 잘 안됐지만 그래도 이렇게 예제 코드로 보니 이해가 좀 됐다!

그냥 간단히 얘기하자면 예전 시스템을 새로운 시스템이랑 연결을 시켜야 하는데 어댑터 패턴을 쓰지 않는다면

굉장히 복잡해지고 어려워 질 것이다. 그래서 어댑터 패턴을 사용하는 것!

반응형
반응형

✅ 어댑터 패턴이란?

서로 다른 인터페이스를 가진 두 클래스가 함께 동작하도록 중간에 "변환기" 역할을 해주는 패턴

📌 한 줄 요약:
"호환되지 않는 인터페이스를 연결해주는 중간 어댑터 클래스"


✅ 언제 쓰일까?

  • 기존 코드 or 라이브러리 인터페이스를 바꾸지 않고 사용하고 싶을 때
  • 인터페이스 불일치 때문에 직접 호출이 안 될 때
  • 예전 코드와 새로운 코드를 자연스럽게 연결하고 싶을 때

✅ 예제 시나리오: 충전기 어댑터

  • 한국 콘센트는 220V
  • 미국 전자제품은 110V

어댑터를 끼우면 한국 콘센트에 미국 기기를 연결할 수 있어!


✅ C# 코드 예제

1️⃣ 기존 시스템 (한국 방식)

interface ITarget
{
    void Request();  // 우리가 원하는 방식
}

class KoreanCharger : ITarget
{
    public void Request()
    {
        Console.WriteLine("220V로 충전합니다.");
    }
}

2️⃣ 호환되지 않는 외부 클래스 (미국 방식)

 
class AmericanDevice
{
    public void ConnectWith110V()
    {
        Console.WriteLine("110V에 연결되었습니다.");
    }
}

3️⃣ 어댑터 클래스

class Adapter : ITarget
{
    private AmericanDevice _device;

    public Adapter(AmericanDevice device)
    {
        _device = device;
    }

    public void Request()
    {
        // 220V 요청을 110V 방식으로 변환
        _device.ConnectWith110V();
    }
}

4️⃣ 사용 코드

ITarget charger1 = new KoreanCharger();
charger1.Request(); // ✅ 220V로 충전합니다.

ITarget charger2 = new Adapter(new AmericanDevice());
charger2.Request(); // ✅ 110V에 연결되었습니다.

✅ 구조 요약 (클래스 관계)

[ITarget] <─── [Adapter] ───> [AmericanDevice]
          ↑
[KoreanCharger] (직접 구현)

✅ 어댑터 패턴 종류

방식 설명
객체 어댑터 어댑터가 기존 객체를 포함해서 호출 (💡 C#에서 주로 사용)
클래스 어댑터 어댑터가 상속을 통해 연결 (C#은 다중 상속 안 되므로 제한적)
 

✅ 실제 사용 예 (Unity에서도 유용)

  • Unity의 InputSystem이 바뀌었을 때, 기존 방식과 연결할 때
  • 외부 API 라이브러리와 내부 구조 연결할 때
  • 레거시 시스템 유지하면서 새 구조 연동할 때

✅ 요약

항목 설명
목적 서로 다른 인터페이스를 연결
키워드 "변환기", "중간 연결자"
구조 기존 인터페이스 + 어댑터 클래스 + 호환 불가 객체
실용성 외부 시스템 통합, 레거시 코드 연동 시 유용

 

흠..이렇게 봐서는 어댑터 패턴이 얼마나 중요한지 아직은 잘 모르겠다 좀 더 자세한 예시 코드를 보자.

일단 어댑터를 사용하는 방법을 제대로 알아보죠!

 

✅ 1. namespace Adapter가 왜 등장할까?

🔸 namespace는 이름 충돌을 방지하고 코드를 구조적으로 정리하기 위한 C#의 기능이야.

예를 들어, 이런 상황 생각해봐:

// Game 안에 있는 Enemy
namespace Game
{
    public class Enemy { }
}

// 외부에서 받아온 LegacyEnemy도 Enemy 클래스가 있음
namespace Legacy
{
    public class Enemy { }
}

이런 경우 Enemy가 둘이라 충돌해.
그래서 Game.Enemy, Legacy.Enemy처럼 네임스페이스를 명시해줘야 돼.


✅ 2. 어댑터 쓸 때도 마찬가지

보통 어댑터 코드는 별도의 Adapter 네임스페이스 안에 넣어 정리해.

namespace Adapter
{
    public class LegacyEnemyAdapter : MonoBehaviour, IEnemy
    {
        ...
    }
}

그리고 다른 코드에서 사용할 때는 이렇게 써:

using Adapter;

// 또는 명시적으로 접근
Adapter.LegacyEnemyAdapter adapter = new Adapter.LegacyEnemyAdapter();

✅ 3. 언제 Adapter.를 붙여야 할까?

상황 설명
using Adapter; 있음 그냥 LegacyEnemyAdapter 라고만 써도 됨
using Adapter; 없음 Adapter.LegacyEnemyAdapter 이렇게 전체 경로로 써야 함
이름 충돌 있을 때 반드시 Adapter. 붙여서 명확하게 구분해야 함
 

✅ Unity에서 실제로는?

Unity에서는 대부분 클래스가 MonoBehaviour를 상속하고
스크립트를 오브젝트에 붙여서 인스펙터에서 연결하니까
Adapter.LegacyEnemyAdapter 라고 직접 쓰는 일은 드물어.

하지만 코드에서 직접 생성하거나, 네임스페이스 충돌이 있을 땐 명시적으로 써줘야 해:

IEnemy enemy = new Adapter.LegacyEnemyAdapter();

✅ 한 줄 요약

어댑터 클래스를 namespace Adapter 안에 넣으면
구조를 명확히 하고, 다른 클래스 이름과 충돌하지 않게 도와준다.
필요할 땐 Adapter.ClassName 으로 명시적으로 접근하면 된다.

 

실제로 어댑터를 사용할때는 namespace를 사용하는듯합니다.

그리고 어댑터가 적용된거는 using으로만 작성해도 충분한듯해요!

다음 어댑터 제대로된 예제 코드를 보죠!

 

🎮 예제 시나리오:

우리 게임은 IInputHandler 라는 인터페이스로 입력을 처리하고 있음.
하지만 외부에서 제공된 LegacyInput 클래스는 우리가 쓰는 구조와 다름.
→ 어댑터를 만들어서 LegacyInput을 IInputHandler처럼 사용할 수 있도록 하자.


✅ 1. 인터페이스: 우리가 사용하는 입력 방식

// IInputHandler.cs
public interface IInputHandler
{
    void HandleInput();
}

✅ 2. 정상적인 Unity 입력 구현 (키보드로 움직임)

// KeyboardInputHandler.cs
using UnityEngine;

public class KeyboardInputHandler : MonoBehaviour, IInputHandler
{
    public void HandleInput()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log("스페이스바 눌림 (키보드)");
        }
    }
}

✅ 3. 외부에서 가져온 입력 시스템 (호환 안 됨)

// LegacyInput.cs
using UnityEngine;

public class LegacyInput
{
    public bool IsTouched()
    {
        // 가상의 외부 입력 방식 (예: 터치스크린)
        return Input.touchCount > 0;
    }
}

✅ 4. 어댑터 클래스 만들기

// Adapter/LegacyInputAdapter.cs
using UnityEngine;
using AdapterNamespace;

namespace AdapterNamespace
{
    public class LegacyInputAdapter : MonoBehaviour, IInputHandler
    {
        private LegacyInput _legacyInput;

        private void Awake()
        {
            _legacyInput = new LegacyInput();
        }

        public void HandleInput()
        {
            if (_legacyInput.IsTouched())
            {
                Debug.Log("터치 입력 감지됨 (어댑터)");
            }
        }
    }
}

✅ 5. 플레이어 컨트롤러 — 어댑터든 키보드든 상관 없이 처리 가능!

// Player.cs
using UnityEngine;

public class Player : MonoBehaviour
{
    public MonoBehaviour inputSource;

    private IInputHandler _inputHandler;

    private void Start()
    {
        _inputHandler = inputSource as IInputHandler;

        if (_inputHandler == null)
        {
            Debug.LogError("inputSource는 IInputHandler를 구현해야 합니다!");
        }
    }

    private void Update()
    {
        _inputHandler?.HandleInput();
    }
}

✅ Unity 인스펙터 설정

  1. Player 오브젝트에 Player.cs 컴포넌트 추가
  2. inputSource 슬롯에 아래 중 하나를 드래그:
    • KeyboardInputHandler 컴포넌트 붙인 오브젝트
    • LegacyInputAdapter 컴포넌트 붙인 오브젝트

➡️ 어떤 걸 연결해도 작동 ✅


✅ 결과

연결된 컴포넌트 결과
KeyboardInputHandler 키보드 스페이스 입력 처리
LegacyInputAdapter 터치 입력 처리 (외부 시스템)
 

✅ 요약 구조

[Player] → IInputHandler ← [KeyboardInputHandler]
                          ← [LegacyInputAdapter → LegacyInput]
  • LegacyInput 은 우리가 바꿀 수 없는 외부 시스템
  • LegacyInputAdapter 가 어댑터 역할
  • Player 입장에선 어떤 입력 시스템이든 같은 방식으로 처리함

이렇게 예제 코드로 예시를 들어봤는데요 흠.. 사실 저도 아직까지 막 와닿진 않네요 ㅠㅜ

다음에 유니티로 직접 개발해봐야겠습니다! 사실 직접해보는게 제일 빠르고 이해가 좋은거같아요!

반응형

C# - goto

Dev_Jen
|2025. 7. 4. 11:39
반응형

✅ goto란?

goto는 프로그램의 흐름을 특정 위치(레이블)로 "강제로" 이동시키는 문법이야.

goto 레이블이름;
...
레이블이름:
    실행할 코드;

✅ 아주 단순히 말하면:

"코드 중간 어딘가로 점프!"


✅ 간단한 예제

int i = 0;

start:
Console.WriteLine(i);
i++;

if (i < 5)
    goto start;  // start로 이동 (반복처럼 동작)

🟰 위 코드는 사실상 while문처럼 동작해.


✅ goto는 언제 쓰나?

  • switch문에서 중첩된 case 건너뛸 때
  • 에러 발생 시 빠르게 특정 cleanup으로 이동
  • 매우 드물게 복잡한 상태 머신 구조

✅ switch문에서의 goto

 
int num = 2;

switch (num)
{
    case 1:
        Console.WriteLine("One");
        break;
    case 2:
        Console.WriteLine("Two");
        goto case 1; // case 1으로 이동!
    default:
        Console.WriteLine("Default");
        break;
}

📝 출력:

Two  
One

✅ 사용 시 주의사항 ❗

  • goto는 코드를 복잡하게 만들고,
  • 흐름을 예측하기 어렵게 만들기 때문에
  • 되도록 사용하지 않는 것이 원칙이야

📌 대부분의 경우 for, while, if로 해결 가능!


✅ 요약 정리

항목 설명
goto 코드의 흐름을 특정 지점으로 강제 이동
사용처 switch case 점프, 에러 처리, 특별한 상황
추천 여부 ❌ 일반 코드에서는 사용 자제
대체 if, while, return, break, continue 등

✅ 한 줄 요약

goto는 레이블로 점프하는 문법이지만, 가독성 나빠서 정말 필요한 상황에서만 조심스럽게 사용해야 한다.

 

C에서 배웠어서 원래 알고있는 내용이였지만 C#에도 있는줄은 몰랐다 ㅎㅎ..

아무래도 원하는곳으로 이동할 수 있게 만들어주지만 너무 많이 사용하게되면 코드가 복잡해지고 왔다갔다해서 더 이상해질수도 있을듯하다. 사용한다면 정말 중요한 부분에만 사용하는걸로..

반응형
반응형

✅ 델리게이트(Delegate)란?

📌 델리게이트는 메서드를 참조할 수 있는 타입이다.
쉽게 말하면, **"함수를 변수처럼 다루기 위한 문법"**이야.

C#에서 함수 자체는 변수에 담을 수 없지만,
델리게이트를 통해 **함수(메서드)를 가리키는 참조(주소)**를 저장하고 호출할 수 있어.


✅ 왜 쓸까?

델리게이트는 다음과 같은 상황에서 유용해:

  • 콜백 함수 구현
  • 이벤트(Event) 처리
  • 전략(Strategy) 패턴처럼 동작의 유연한 교체
  • 다형성 없이 다양한 함수 호출 처리

✅ 델리게이트 기본 선언 및 사용

// 1. 델리게이트 선언
delegate void PrintDelegate(string message);

// 2. 사용할 메서드
void PrintHello(string msg)
{
    Console.WriteLine("Hello " + msg);
}

// 3. 델리게이트 변수 생성 및 할당
PrintDelegate printer = PrintHello;

// 4. 델리게이트 호출 (함수처럼 사용 가능)
printer("재은"); // Hello 재은

✅ 델리게이트의 중요한 특징

특징 설명
형식 안전 델리게이트는 선언된 시그니처(매개변수 타입, 반환형)를 따라야 함
멀티 캐스트 가능 여러 메서드를 델리게이트에 연결할 수 있음 (+=, -=)
익명 함수, 람다와 호환 delegate 키워드 또는 lambda 표현식으로 할당 가능

✅ 익명 메서드 & 람다식으로 쓰기

🔸 익명 메서드

PrintDelegate printer = delegate(string msg)
{
    Console.WriteLine("Hello " + msg);
};

🔸 람다식

PrintDelegate printer = (msg) => Console.WriteLine("Hello " + msg);

✅ 델리게이트 종류

종류 설명
일반 델리게이트 위에서 직접 선언한 것
Action<T> 반환값이 없는 델리게이트 (void)
Func<T, TResult> 반환값이 있는 델리게이트
Predicate<T> bool을 반환하는 델리게이트

✅ Action, Func, Predicate 예시

 
Action<string> sayHi = (name) => Console.WriteLine($"Hi, {name}");
Func<int, int, int> sum = (a, b) => a + b;
Predicate<int> isEven = (num) => num % 2 == 0;

sayHi("재은");          // Hi, 재은
Console.WriteLine(sum(3, 5));  // 8
Console.WriteLine(isEven(4));  // true

✅ 멀티캐스트 델리게이트 (여러 메서드 연결)

delegate void Notifier();
void A() => Console.WriteLine("A 호출");
void B() => Console.WriteLine("B 호출");

Notifier notify = A;
notify += B;

notify(); // A 호출, B 호출

✅ 델리게이트 vs 이벤트

항목 델리게이트 이벤트(Event)
접근 외부에서 자유롭게 호출 가능 외부에서 직접 호출 불가
목적 콜백, 전략 패턴 등 이벤트 처리 전용
사용 위치 일반 메서드 전달 등 주로 UI, 버튼 클릭, 상태 변화

✅ 정리 요약

항목 설명
델리게이트 메서드를 참조할 수 있는 타입
사용 목적 콜백, 이벤트, 유연한 함수 실행
문법 delegate, Action, Func, Predicate
특징 형식 안전, 멀티캐스트 가능, 람다 지원

델리게이트란 함수를 변수처럼 사용하는것도 알겠고 람다식을 이용하면 더 쉽게 잘 사용할 수 있는것도 알겠다 근데

=> 이표시가 무슨 표시인지를 모르겠다.. 물어보니까 람다 연산자라고 하는데 자세히 알아봅시다!

✅ => 는 뭐야?

"goes to", 혹은 "이 함수는 이렇게 작동해!" 라고 해석하면 좋아.

(parameters) => expression_or_statement_block

이 구조는 람다식(lambda expression) 이라고 불리는 문법으로,
익명 함수(이름 없는 함수)를 만들기 위한 간결한 문법이야.


✅ 예시로 설명

Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 5)); // 출력: 8
  • (a, b) → 매개변수
  • => → 람다 연산자
  • a + b → 반환할 표현식 (return 생략 가능)

→ 위 코드는 "a와 b를 받아서 a + b를 반환하는 함수" 를 만들고, add에 담은 거야.

Func<int, int, int> add = (a, b) => a + b;

이 부분이 하나도 이해가 안된다.. 어떻게 저렇게 나온거지?...한번 물어보겠습니다

✅ 코드 다시 보기

Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 5)); // 출력: 8

✅ 이건 무슨 뜻일까?

💡 한 줄 해석:

add라는 이름의 "함수 변수"를 만들고,
이 함수는 int 2개를 받아서 int 하나를 반환하는 함수야.

즉, 이건 아래 함수와 같은 의미야:

int Add(int a, int b)
{
    return a + b;
}

하지만 Func<int, int, int>을 사용하면,
함수를 변수처럼 담아서, 더 유연하게 쓸 수 있어.


✅ 코드 완전 해부

부분 의미
Func<int, int, int> 매개변수 2개 (int, int), 반환값 int인 함수 타입
(a, b) 매개변수
=> 람다 연산자
a + b 반환할 값 (return 생략 가능)

아 이 부분에서 제가 궁금했던 Func<int, int, int>가 나오네요! 매개변수 2개를 사용하는 int인 함수 타입이라고 하네요!!! 

궁금증 해결! 완전 해소됐네여!! 굳!!!!

=> 이 연산자도 그냥 람다 연산자니 외우던지..해야겠네여ㅎㅎ..

근데 확실히 더 코드가 간결해지고 이쁘게 쓸 수 있는듯 하네여


✅ 일반 함수와 비교

// 일반적인 함수 정의
int Add(int a, int b)
{
    return a + b;
}

이걸 변수에 저장해서 쓸 수 있도록 만든 게 바로:

Func<int, int, int> add = (a, b) => a + b;

이제 add(3, 5) 하면 → a=3, b=5 → a + b = 8


✅ 다른 예시로 익혀보기

1️⃣ 문자열 길이 구하는 함수

Func<string, int> getLength = s => s.Length;
Console.WriteLine(getLength("hello")); // 5
  • 매개변수 1개 (string)
  • 반환값: int

2️⃣ 두 수의 곱 구하는 함수

Func<int, int, int> multiply = (x, y) => x * y;
Console.WriteLine(multiply(4, 6)); // 24

3️⃣ 인사 출력하는 Action (반환 없음)

Action<string> greet = name => Console.WriteLine("Hi, " + name);
greet("재은"); // Hi, 재은

✅ 요약

문법 의미
Func<T1, T2, TResult> 입력 T1, T2 → 출력 TResult 함수
Action<T> 입력 T → 반환값 없음 (void)
(x, y) => x + y 람다식으로 함수 정의

✅ 다양한 형태의 예시

1. 표현식 람다 (한 줄)

Func<int, int> square = x => x * x;

→ x를 받아서 x * x를 반환하는 함수


2. 문장 블록 람다 (여러 줄)

Action<string> greet = name => {
    Console.WriteLine("안녕!");
    Console.WriteLine("나는 " + name);
};

→ name을 받아서 여러 문장을 실행하는 함수


✅ 어떤 상황에서 쓰여?

  • 델리게이트에 함수 전달할 때
  • LINQ 쿼리에서 (Where(x => x > 0))
  • 이벤트 핸들러
  • 간단한 콜백 함수

✅ 정리

기호 의미
=> 람다 연산자. "함수 정의는 이렇게!"
(x) => x * 2 x를 받아서 x * 2를 반환하는 함수

이렇게 델리게이트와 람다 연산자에 대해서 알아봤는데여 굉장히 흥미롭고 재밌네요!!ㅎㅎ

궁금증도 풀렸고 재밌는 공부가 됐습니다! 앞으로 유니티 개발할때 자주 사용하면 좋겠네여!

반응형

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

C# - Adpater Pattern2 C# 코드예제  (2) 2025.07.06
C# - goto  (0) 2025.07.04
C# - Queue(큐) vs Stack(스택) + 메모리구조  (2) 2025.07.04
C# - List vs Array(리스트 vs 배열)  (1) 2025.07.04
C# - Collection(컬렉션)  (0) 2025.07.04
반응형

✅ 핵심 차이 한 줄 요약

자료구조 개념
큐(Queue) FIFO: 먼저 들어간 게 먼저 나온다 (First-In First-Out)
스택(Stack) LIFO: 나중에 들어간 게 먼저 나온다 (Last-In First-Out)

✅ 실생활 비유

자료구조 비유 예시
Queue 줄 서기, 은행 번호표, 프린터 대기열
Stack 책 쌓기, 접시 쌓기, 웹 브라우저 뒤로가기

✅ C# 예제 코드

📌 Queue

Queue<string> q = new Queue<string>();
q.Enqueue("철수");
q.Enqueue("영희");
Console.WriteLine(q.Dequeue()); // 철수
  • Enqueue() : 데이터 넣기
  • Dequeue() : 가장 먼저 들어온 데이터 꺼내기

📌 Stack

Stack<string> s = new Stack<string>();
s.Push("철수");
s.Push("영희");
Console.WriteLine(s.Pop()); // 영희
  • Push() : 데이터 넣기
  • Pop() : 가장 마지막에 들어온 데이터 꺼내기

✅ 메모리 구조 (예시)

🔸 Queue 구조

Enqueue → [1] [2] [3] → Dequeue
                ↑
              순서대로 나감

🔸 Stack 구조

Push → [1] [2] [3] ← Pop
                ↑
           마지막 값부터 꺼냄

✅ 기능 비교

항목 Queue Stack
삽입 Enqueue Push
제거 Dequeue Pop
최상단 요소 보기 Peek Peek
순서 FIFO LIFO
사용 예 작업 순서 처리, 이벤트 대기열 재귀, 뒤로가기, Undo

✅ 정리 요약

항목 Queue Stack
구조 선입선출 (FIFO) 후입선출 (LIFO)
메서드 Enqueue, Dequeue, Peek Push, Pop, Peek
순서 먼저 넣은 것이 먼저 나감 나중에 넣은 것이 먼저 나감
실생활 예시 줄서기, 은행, 프린터 대기 책 더미, 웹브라우저 뒤로가기

물론 스택과 큐도 힙에 저장되겠지만 더 자세히 알고싶어서 다시 물어봤습니다!

 

✅ 왜 힙에 저장될까?

C#에서 Queue<T>, Stack<T>는 클래스(참조 타입)이기 때문이야.
객체가 생성되면 힙에 올라감, 스택에는 참조(주소값) 만 저장됨.

Queue<int> q = new Queue<int>();
  • q는 스택에 있음 → 참조 변수
  • new Queue<int>() 는 힙에 할당됨 → 실제 Queue 객체

같은 구조가 Stack<T>에도 그대로 적용돼.

GPT가 만들어준 그림인데 Internal Array가 뭔 소리인지 이해가 안되서 다시 물어봤어여ㅎㅎ..

✅ "internal array"란?

Queue<T>나 Stack<T> 같은 컬렉션 클래스는
내부적으로 데이터를 담기 위해 배열(T[ ])을 사용해.
이 배열을 흔히 내부 배열, 또는 백업 배열 (backing array) 라고 부르는데, 영어로는:

  • internal array
  • underlying array
  • backing array

라고 표현할 수 있어. 따라서 표현 자체는 맞는 말이야!

표현 자체는 맞는 말이라고 합니다!


✅ 메모리 구조 예시

 
Queue<int> q = new Queue<int>();
q.Enqueue(10);
[스택]
q ──▶ (힙 주소)

[힙]
Queue 객체
 └─ 내부 배열(int[]) = [10, ...]
  • 내부적으로 배열을 기반으로 구현되어 있음
  • 그 배열(int[]) 역시 힙에 생성됨

📌 즉, 힙 안에 Queue 객체가 있고 → Queue 내부에 배열도 힙에 있음
→ 이걸 "힙 안에 힙" 구조라고도 말할 수 있어.


✅ 한 줄 요약

Queue<T>, Stack<T>는 참조 타입 클래스이므로
실제 데이터와 구조 모두 힙에 저장된다.
스택에는 변수명(q, s 등)의 참조(주소) 만 존재한다.

 

반응형