2023/08/17 TIL

김도현·2023년 8월 17일
0

TIL

목록 보기
22/76

들어가기 앞서

강의

[스파르타코딩클럽] C# 문법 종합반 - 4주차

알고리즘 문제시트

  • 몫 구하기 - 사칙연산

    using System;
    
    public class Solution {
        public int solution(int num1, int num2) {
            return num1/num2;;
        }
    }
  • 최빈값 구하기 - 사칙연산, 배열, 수학

    using System;
    
    public class Solution {
        public int solution(int[] array) {
            int answer = 0;
            int before = 0;
            int nowCount = 0;
            int[] count = new int[1000];
            for (int i = 0; i < array.Length; i++)
                count[array[i]] = count[array[i]] + 1;
            for (int i = 0; i < 1000; i++)
            {
                if (nowCount <= count[i])
                {
                    before = nowCount;
                    nowCount = count[i];
                    answer = i;
                }
            }
            if (before == nowCount)
                answer = -1;
            return answer;
        }
    }
  • 배열 두 배 만들기 - 사칙연산, 조건문, 배열

    using System;
    
    public class Solution {
        public int[] solution(int[] numbers) {
            int[] answer = new int[numbers.Length];
            for(int i =0; i < numbers.Length; i++)
            {
                answer[i] = numbers[i] * 2;
            }
            return answer;
        }
    }
  • 배열 뒤집기 - 수학, 배열

    using System;
    
    public class Solution {
        public int[] solution(int[] num_list) {
            int[] answer = new int[num_list.Length];
                for (int i = 0; i < num_list.Length; i++)
                    answer[i] = num_list[num_list.Length - i - 1];
            return answer;
        }
    }

오늘 배운 것

인터페이스(Interface)

사용하는 이유

1. 코드의 재사용성

인터페이스를 사용하면 다른 클래스에서 해당 인터페이스를 구현하여 기능을 공유할 수 있다.

2. 다중 상속 제공

c#에서는 클래스는 단일 상속만을 지원, 인터페이스는 다중 상속 지원
클래스가 여러 인터페이스를 구현함으로써 여러 개의 기능을 조합할 수 있다.

3. 유연한 설계

인터페이스를 사용하면 클래스와 인터페이스 간에 느슨한 결합을 형성 가능
클래스는 인터페이스를 구현하기만 하면 되므로, 클래스의 내부 구현에 대한 변경 없이 인터페이스의 동작을 변경하거나 새로운 인터페이스를 추가할 수 있다.

인터페이스 특징

  • 인터페이스란 클래스가 구현해야 하는 멤버들을 정의하는 것입니다.
  • 인터페이스는 클래스의 일종이 아니며, 클래스에 대한 제약 조건을 명시하는 것입니다.
  • 클래스가 인터페이스를 구현할 경우, 모든 인터페이스 멤버를 구현해야 합니다.
  • 인터페이스는 다중 상속을 지원합니다.

사용 방법

interface IMyInterface
{
    void Method1();
    int Method2(string str);
}
class MyClass : IMyInterface
{
    public void Method1()
    {
        // 구현
    }

    public int Method2(string str)
    {
        // 구현
        return 0;
    }
}

추상클래스와 차이

인터페이스의 장점

  • 인터페이스는 추상적인 동작만 정의(반환 타입, 반입하는 타입, 메서드명만 선언)하고, 구현(내용)을 갖지 않습니다.
  • 다중상속 가능
  • 클래스들 간의 결합도를 낮추고, 유연한 상호작용을 가능
  • 코드의 재사용성과 확장성을 향상

인터페이스의 단점

  • 단점으로는 인터페이스를 구현하는 클래스가 모든 동작을 구현해야 한다.

추상클래스의 장점

  • 일부 동작의 구현을 가지며, 추상 메서드를 포함 가능
  • 단일 상속만 가능, 다른 클래스와 함께 상속 계층 구조를 형성
  • 공통된 동작을 추상화하여 코드의 중복을 방지하고, 확장성을 제공합니다.
  • 구현된 동작을 가지고 있기 때문에, 하위 클래스에서 재정의하지 않아도 됨

추상클래스의 단점

  • 다중 상속이 불가능하고, 상속을 통해 밀접하게 결합된 클래스들을 형성하므로 유연성이 제한

열거형(Enums)

사용하는 이유

1. 가독성:

열거형을 사용하면 일련의 연관된 상수들을 명명할 수 있습니다. 이를 통해 코드의 가독성이 향상되고, 상수를 사용할 때 실수로 잘못된 값을 할당하는 것을 방지

2. 스위치 문과의 호환성:

열거형은 스위치 문과 함께 사용될 때 유용합니다. 열거형을 사용하면 스위치 문에서 다양한 상수 값에 대한 분기를 쉽게 작성

사용 방법

  • 열거형 정의
enum MyEnum
{
	Value1,
	Value2,
	Value3
}
  • 열거형 사용
MyEnum myEnum = MyEnum.Value1;
  • 열거형 상수 값 지정
enum MyEnum
{
	Value1 = 10,
	Value2,
	Value3 = 20
}
  • 열거형 형변환
int intValue = (int)MyEnum.Value1;  // 열거형 값을 정수로 변환
MyEnum enumValue = (MyEnum)intValue;  // 정수를 열거형으로 변환
  • 스위치문과의 사용
switch(enumValue)
{
    case MyEnum.Value1:
        // Value1에 대한 처리
        break;
    case MyEnum.Value2:
        // Value2에 대한 처리
        break;
    case MyEnum.Value3:
        // Value3에 대한 처리
        break;
    default:
        // 기본 처리
        break;
}

예외 처리

자세한 내용을 해당 링크에

박싱과 언박싱

// 박싱과 언박싱
int num1 = 10;
object obj = num1; // 박싱 : 값형을 참조형으로
int num2 = (int)obj; // 언박싱 : 참조형을 값형으로
Console.WriteLine("num1: " + num1); // 출력 결과: 10
Console.WriteLine("num2: " + num2); // 출력 결과: 10

활용 예시

List<object> myList = new List<object>();

// 박싱: 값 형식을 참조 형식으로 변환하여 리스트에 추가
int intValue = 10;
myList.Add(intValue); // int를 object로 박싱하여 추가

float floatValue = 3.14f;
myList.Add(floatValue); // float를 object로 박싱하여 추가

// 언박싱: 참조 형식을 값 형식으로 변환하여 사용
int value1 = (int)myList[0]; // object를 int로 언박싱
float value2 = (float)myList[1]; // object를 float로 언박싱

델리게이트(Delegate)

  • 델리게이트(delegate)는 메서드를 참조하는 타입입니다.
  • 다른 프로그래밍 언어에서는 함수 포인터라는 용어를 사용하기도 합니다.
  • 델리게이트를 이용하면 메서드를 매개변수로 전달하거나 변수에 할당할 수 있습니다.

사용 방법

  • 메서드 등록해서 사용하기
delegate int Calculate(int x, int y);

static int Add(int x, int y)
{
    return x + y;
}

class Program
{
    static void Main()
    {
        // 메서드 등록
        Calculate calc = Add;

        // 델리게이트 사용
        int result = calc(3, 5);
        Console.WriteLine("결과: " + result);
    }
}
  • 하나 이상의 메서드 등록하기
delegate void MyDelegate(string message);

static void Method1(string message)
{
    Console.WriteLine("Method1: " + message);
}

static void Method2(string message)
{
    Console.WriteLine("Method2: " + message);
}

class Program
{
    static void Main()
    {
        // 델리게이트 인스턴스 생성 및 메서드 등록
        MyDelegate myDelegate = Method1;
        myDelegate += Method2;

        // 델리게이트 호출
        myDelegate("Hello!");

        Console.ReadKey();
    }
}

사용 예시

  • event 를 붙여서 사용
  • event는 할당연산자( = )를 사용할 수 없으며, 클래스 외부에서는 직접 이벤트를 호출할 수 없다.
// 델리게이트 선언
public delegate void EnemyAttackHandler(float damage);

// 적 클래스
public class Enemy
{
    // 공격 이벤트
    public event EnemyAttackHandler OnAttack;

    // 적의 공격 메서드
    public void Attack(float damage)
    {
        // 이벤트 호출
        OnAttack?.Invoke(damage);
				// null 조건부 연산자
				// null 참조가 아닌 경우에만 멤버에 접근하거나 메서드를 호출
    }
}

// 플레이어 클래스
public class Player
{
    // 플레이어가 받은 데미지 처리 메서드
    public void HandleDamage(float damage)
    {
        // 플레이어의 체력 감소 등의 처리 로직
        Console.WriteLine("플레이어가 {0}의 데미지를 입었습니다.", damage);
    }
}

// 게임 실행
static void Main()
{
    // 적 객체 생성
    Enemy enemy = new Enemy();

    // 플레이어 객체 생성
    Player player = new Player();

    // 플레이어의 데미지 처리 메서드를 적의 공격 이벤트에 추가
    enemy.OnAttack += player.HandleDamage;

    // 적의 공격
    enemy.Attack(10.0f);
}

람다(Lambda)

사용 방법

  • 형식
(parameter_list) => expression
  • 정의하기
Calculate calc = (x, y) => 
{	
		return x + y;
};

Calculate calc = (x, y) => x + y;

사용 예시

using System;

// 델리게이트 선언
delegate void MyDelegate(string message);

class Program
{
    static void Main()
    {
        // 델리게이트 인스턴스 생성 및 람다식 할당
        MyDelegate myDelegate = (message) =>
        {
            Console.WriteLine("람다식을 통해 전달된 메시지: " + message);
        };

        // 델리게이트 호출
        myDelegate("안녕하세요!");

        Console.ReadKey();
    }
}
  • 게임의 분기 시작의 알리기
// 델리게이트 선언
public delegate void GameEvent();

// 이벤트 매니저 클래스
public class EventManager
{
    // 게임 시작 이벤트
    public event GameEvent OnGameStart;

    // 게임 종료 이벤트
    public event GameEvent OnGameEnd;

    // 게임 실행
    public void RunGame()
    {
        // 게임 시작 이벤트 호출
        OnGameStart?.Invoke();

        // 게임 실행 로직

        // 게임 종료 이벤트 호출
        OnGameEnd?.Invoke();
    }
}

// 게임 메시지 클래스
public class GameMessage
{
    public void ShowMessage(string message)
    {
        Console.WriteLine(message);
    }
}

// 게임 실행
static void Main()
{
    // 이벤트 매니저 객체 생성
    EventManager eventManager = new EventManager();

    // 게임 메시지 객체 생성
    GameMessage gameMessage = new GameMessage();

    // 게임 시작 이벤트에 람다 식으로 메시지 출력 동작 등록
    eventManager.OnGameStart += () => gameMessage.ShowMessage("게임이 시작됩니다.");

    // 게임 종료 이벤트에 람다 식으로 메시지 출력 동작 등록
    eventManager.OnGameEnd += () => gameMessage.ShowMessage("게임이 종료됩니다.");

    // 게임 실행
    eventManager.RunGame();
}

Func 과 Action

사용 방법

  • Func 예제
// Func를 사용하여 두 개의 정수를 더하는 메서드
int Add(int x, int y)
{
    return x + y;
}

// Func를 이용한 메서드 호출
Func<int, int, int> addFunc = Add;
int result = addFunc(3, 5);
Console.WriteLine("결과: " + result);
  • Action 예제
// Action을 사용하여 문자열을 출력하는 메서드
void PrintMessage(string message)
{
    Console.WriteLine(message);
}

// Action을 이용한 메서드 호출
Action<string> printAction = PrintMessage;
printAction("Hello, World!");

사용 예시

// 게임 캐릭터 클래스
class GameCharacter
{
    private Action<float> healthChangedCallback;

    private float health;

    public float Health
    {
        get { return health; }
        set
        {
            health = value;
            healthChangedCallback?.Invoke(health);
        }
    }

    public void SetHealthChangedCallback(Action<float> callback)
    {
        healthChangedCallback = callback;
    }
}

// 게임 캐릭터 생성 및 상태 변경 감지
GameCharacter character = new GameCharacter();
character.SetHealthChangedCallback(health =>
{
    if (health <= 0)
    {
        Console.WriteLine("캐릭터 사망!");
    }
});

// 캐릭터의 체력 변경
character.Health = 0;

LINQ(Language Integrated Query)

  • .NET 프레임워크에서 제공되는 쿼리 언어 확장
  • 데이터 소스(예: 컬렉션, 데이터베이스, XML 문서 등)에서 데이터를 쿼리하고 조작하는데 사용됩니다.
  • 데이터베이스 쿼리와 유사한 방식으로 데이터를 필터링, 정렬, 그룹화, 조인 등 다양한 작업을 수행할 수 있습니다.
  • LINQ는 객체, 데이터베이스, XML 문서 등 다양한 데이터 소스를 지원합니다.

구조

var result = from 변수 in 데이터소스
             [where 조건식]
             [orderby 정렬식 [, 정렬식...]]
             [select];

  • var 키워드는 결과 값의 자료형을 자동으로 추론합니다.
  • from 절에서는 데이터 소스를 지정합니다.
  • where 절은 선택적으로 사용하며, 조건식을 지정하여 데이터를 필터링합니다.
  • orderby 절은 선택적으로 사용하며, 정렬 방식을 지정합니다.
  • select 절은 선택적으로 사용하며, 조회할 데이터를 지정합니다.

사용 방법

// 데이터 소스 정의 (컬렉션)
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

// 쿼리 작성 (선언적인 구문)
var evenNumbers = from num in numbers
                  where num % 2 == 0
                  select num;

// 쿼리 실행 및 결과 처리
foreach (var num in evenNumbers)
{
    Console.WriteLine(num);
}

Nullable 형

사용 방법

// Nullable 형식 변수 선언
int? nullableInt = null;
double? nullableDouble = 3.14;
bool? nullableBool = true;

// 값 할당 및 접근
nullableInt = 10;
int intValue = nullableInt.Value;

// null 값 검사
if (nullableDouble.HasValue)
{
    Console.WriteLine("nullableDouble 값: " + nullableDouble.Value);
}
else
{
    Console.WriteLine("nullableDouble은 null입니다.");
}

// null 병합 연산자 사용
// nullableInt ?? 0과 같이 사용되며, nullableInt가 null이면 0을 반환합니다.
int nonNullableInt = nullableInt ?? 0;
Console.WriteLine("nonNullableInt 값: " + nonNullableInt);

문자열 빌더

주요 메서드

  • Append: 문자열을 뒤에 추가합니다.
  • Insert: 문자열을 지정한 위치에 삽입합니다.
  • Remove: 지정한 위치에서 문자열을 제거합니다.
  • Replace: 문자열의 일부를 다른 문자열로 대체합니다.
  • Clear: StringBuilder의 내용을 모두 지웁니다.

사용 방법

StringBuilder sb = new StringBuilder();

// 문자열 추가
sb.Append("Hello");
sb.Append(" ");
sb.Append("World");

// 문자열 삽입
sb.Insert(5, ", ");

// 문자열 치환
sb.Replace("World", "C#");

// 문자열 삭제
sb.Remove(5, 2);

// 완성된 문자열 출력
string result = sb.ToString();
Console.WriteLine(result);

기억 할 것 & 진행 사항

Snake Game

화면을 표현할때는 갱신 내용만 변경하면 보다 리소스 소모가 적어진다.

내일 할 일

5강 수강하기 및 알고리즘 문제풀기
숙제 풀기

1개의 댓글

comment-user-thumbnail
2023년 8월 17일

개발자로서 배울 점이 많은 글이었습니다. 감사합니다.

답글 달기