# 20 \~ 29

### 20 C# 인터렉티브

<figure><img src="/files/hsCnBaTcLhL0FTniqoOW" alt=""><figcaption></figcaption></figure>

Visual Studio > 보기 > 다른 창 > C# Interactive

`#help` : 명령어 도움말 `#cls` 또는 `#clear` : 화면 지우기 `#r "dll 파일의 경로"` : 외부 DLL 파일 참조

문자열과 숫자 등 리터럴은 Console.WriteLine() 생략하고 직접 출력 가능

### 21 닷넷 API

마소에서 닷넷 API 검색할 수 있는 사이트 제공해준다.

닷넷에서 제공하는 수학 관련 내장 클래스 Math : Math.Abs(), Math.Max(), Math.Pow(), Math.Floor() 등

`using static System.Math;` 사용하면 Math.Pow()가 아니라 Pow()로 줄여 쓸 수 있다

nameof 연산자로 클래스 또는 메서드 이름 자체를 문자열로 가져올 수 있다

### 22 구조체 사용하기

구조체 : 이름 하나로 서로 다른 데이터 형식을 묶어 관리

C#에는 클래스 있으니까 닷넷 내장 구조체 몇 개만 학습하고 뒤에서 배울 클래스 위주로 사용하면 된다.

#### 22.2 구조체 만들기

```cs
struct Point
{
    public int X;
    public int Y;
}

class StructDemo
{
    static void Main()
    {
        Point point;
        point.X = 100;
        point.Y = 200;
        Console.WriteLine($"X:{point.X}, Y:{point.Y}");
    }
}
```

#### 22.4 구조체 배열

```cs
Point[] points = new Point[2];
```

구조체 배열도 만들 수 있다.

#### 22.6 내장형 구조체

닷넷 프레임워크 내장 구조체 중 자주 사용되는 것들

* DateTime 구조체: 시간/날짜 관련 모든 정보 제공
* TimeSpan 구조체: 시간/날짜 간격에 대한 모든 정보 제공
* Char 구조체: 문자 관련 모든 정보 제공
* Guid 구조체: 절대로 중복되지 않는 유일한 문자열을 생성

**날짜 관련 구조체 사용하기**

```cs
> DateTime.Now.Year
2019
> DateTime now = DateTime.Now;
> Console.WriteLine(now.Date);
2019-09-23 오전 12:00:00
```

DateTime 예제

```cs
class TimeSpanDemo
{
    static void Main()
    {
        // 시간 차 구하기
        TimeSpan dday = Convert.ToDateTime("2024-12-25") - DateTime.Now;
        Console.WriteLine((int)dday.TotalDays);
    }
}
```

TimeSpan 예제

**1부터 8760까지 정수에 해당하는 날짜를 반환하는 함수**

```cs
class GetDateTimeFromYearlyHour
{
    static void Main()
    {
        Console.WriteLine(GetDateTimeFromYearlyHourNumber(1));
        Console.WriteLine(GetDateTimeFromYearlyHourNumber(8760/2));
        Console.WriteLine(GetDateTimeFromYearlyHourNumber(8760));
    }

    static DateTime GetDateTimeFromYearlyHourNumber(int number)
    {
        return (new DateTime(2024, 1, 1, 0, 0, 0)).AddHours(--number);
    }
}
```

**문자 관련 구조체 사용하기**

```cs
Char.IsUpper(a) // 대문자인지?
Char.Number(c) // 숫자형인지?
Char.IsWhiteSpace(d) // 공백 문자인지?
```

**Guid 구조체로 유일한 값 출력하기**

Guid는 GUID(Globally Unique Identifier)를 출력. GUID 값은 실행할 때마다 동일한 값을 만날 확률이 0.

```cs
string unique = Guid.NewGuid().ToString();
```

### 23 열거형 형식 사용하기

#### 23.1 열거형 형식 사용하기

기억하기 어려운 상수들을 기억하기 쉬운 이름 하나로 묶어 관리하는 표현 방식.

**ConsoleColor 열거형으로 콘솔의 전경색 및 배경색 바꾸기**

```cs
    static void Main()
    {
        //전경색
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine("Blue");
        Console.ResetColor();

        //배경색
        Console.BackgroundColor = ConsoleColor.Yellow;
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("Red");
        Console.ResetColor();
    }
```

<figure><img src="/files/TfAZZQU4irlgMsLn4G9c" alt=""><figcaption></figcaption></figure>

신기

#### 23.2 열거형 만들기

```cs
enum Priority
{
	High,
    Normal=5,
    Low // 상수 6
}
```

초기화 안 시키고 쓰는게 기본. 초기화 시키면 그 다음부터의 값도 바뀐다.

상수로만 구분하면 어려우니까 이름을 붙여서 쓰는 느낌.

```cs
    enum Priority
    {
        High,
        Normal,
        Low
    }

    static void Main()
    {
        Priority high = Priority.High;
        Priority normal = Priority.Normal;
        Priority low = Priority.Low;

        Console.WriteLine($"{high}, {normal}, {low}");
    }
```

어째서인지 "High, Normal, Low"가 출력된다. 열거형 변수값을 콘솔에서 문자열로 출력하면 열거형의 멤버 이름이 문자열로 출력된다고 함.

```cs
Animal animal = Animal.Dragon;
int num = (int)animal;
string str = animal.ToString();
```

이러면 num은 상수값, str은 Dragon이 된다. 열거형 값은 변환하는대로 변환된다.

```cs
Animal animal = Animal.Dog;

switch (animal)
{
	case Animal.Chicken:
		break;
	case Animal.Dog:
		break;
}
```

switch 문과 같이 사용하면 유용하다.

```cs
string[] colors = EnumGetNames(cc); // 모든 색상 이름을 반환
```

열거형 이름들을 저장한다.

### 24 클래스 사용하기

클래스

* 속성: 데이터
* 메서드: 로직

클래스의 정의

* 개체를 생성하는 틀(탬플릿)
* 무엇인가를 만들어내는 설계도

**클래스 레벨의 메서드 호출하기**

```cs
class ClassNote
{
    static void Run()
    {
        Console.WriteLine("ClassNote 클래스의 Run 메서드");
    }

    static void Main()
    {
        Run(); // 메서드 레벨: 같은 클래스의 메서드 호출
        ClassNote.Run(); // 클래스 레벨: 클래스.메서드(); 형태로 호출
    }
}
```

**static과 정적 메서드**

C#에서는 `static`을 정적으로 표현한다. 다시 말해, `static`이 붙는 클래스의 모든 멤버는 해당 클래스 내의 누구나 공유해서 접근할 수 있다. `static`이 붙는 메서드를 정적 메서드, 공유 메서드라 한다.

**정적 메서드와 인스턴스 메서드**

```cs
class MyFirstClass
{
    static void StaticMethod() => Console.WriteLine("[1] 정적 메서드");

    void InstanceMethod() => Console.WriteLine("[2] 인스턴스 메서드");

    static void Main()
    {
        MyFirstClass.StaticMethod();
        MyFirstClass my = new MyFirstClass();
        my.InstanceMethod();
    }
}
```

`static` 붙은 정적 메서드는 그냥 호출해도 되고 `static` 안 붙은 인스턴스 메서드는 인스턴스 만든 후 해당 인스턴스 개체를 사용하여 호출

#### 24.4 클래스 시그니처

```
public class Car { }
```

public 액세스 한정자를 생략하면 기본값인 internal을 갖는다. internal: 해당 프로그램 내에서 언제든지 접근 가능하다.

클래스 본문인 중괄호 안에는 메서드, 필드, 속성, 생성자, 소멸자 등이 올 수 있다. 이 모두를 가리켜 클래스 멤버라고 한다.

**클래스 이름 짓기**

클래스 이름은 의미 있는 이름을 사용하면 좋다. 명사를 사용한다. 첫 글자는 꼭 대문자여야 한다. 축약형, 특정 접두사, 언더스코어 같은 특수 문자 쓰지 않는다.

#### 24.5 내장 클래스

인스턴스 생성한 다음에 써야 하는 것도 있고 바로 쓸 수 있는 것도 있고

* String 클래스: 문자열 처리와 관련한 속성과 메서드 제공
* StringBuilder 클래스: 대용량 문자열 처리와 관련된 속성 및 메서드 제공
* Array 클래스: 배열과 관련된 주요 속성 및 메서드 제공
* Environment 클래스: 프로그램 종료, 시스템 폴더, 닷넷 기준 버전, 운영 체제 버전, 컴퓨터 이름, 사용자 이름, 현재 폴더, 문서 폴더 등
* Process 클래스: Start() 메서드로 exe 파일 실행 가능
* Random 클래스: 난수 발생. 사용하려면 인스턴스 생성해야함. (UnityEngine Random이 따로 있어서 이거 쓸 일은 없을듯)
* Stopwatch 클래스: Start()와 Stop() 메서드를 이용해 프로그램 실행 시간 잴 수 있음. 출력은 timer 클래스의 TotalMilliseconds와 Seconds 같은 속성 사용하면 됨.
* regex 클래스: 정규식

#### 24.15 is 연산자로 형식 비교하기

`개체.GetType() == typeof(형식)`의 줄임 표현으로 `개체 is 형식`이 가능하다. ex) `a is int`, `b is string`

#### 24.16 as 연산자로 형식 변환하기

as 연산자는 특정 데이터를 특정 데이터 형식으로 변환하는 데 사용한다. 해당 데이터 형식이면 반환하고 그렇지 않으면 null을 반환한다.

```cs
> object x = 1234;
> string s = x as string;
> s
null
> object x = "1234";
> string s = x as string;
> s
"1234"
```

### 25 문자열 다루기

| **메서드**                       | **설명**                       |
| ----------------------------- | ---------------------------- |
| `Length`                      | 문자열 길이 값 반환                  |
| `ToUpper()`                   | 문자열을 모두 대문자로 변환              |
| `ToLower()`                   | 문자열을 모두 소문자로 변환              |
| `Trim()`                      | 문자열 양쪽 공백을 잘라냄               |
| `Replace(원본문자열, 대상문자열)`       | 원본 문자열을 대상 문자열로 변경           |
| `Substring(문자열인덱스, 길이)`       | 지정된 문자열 인덱스부터 길이만큼 반환        |
| `String.Concat()`             | 문자열 연결                       |
| `ToCharArray()`               | 문자열을 문자 배열로 변환               |
| `Split()`                     | 구분자를 사용하여 문자열 분리             |
| `string.IsNullOrEmpty()`      | `null` 또는 빈 값인지 확인           |
| `string.IsNullOrWhiteSpace()` | `null` 또는 빈 값 또는 공백인지 확인     |
| `IndexOf()`                   | 문자열 앞부분부터 검색해서 특정 문자 첫 등장 위치 |
| `LastIndexOf()`               | 문자열 뒷부분부터 검색해서 특정 문자 첫 등장 위치 |
| `Insert()`                    | 문자열 삽입                       |
| `Remove()`                    | 지정한 위치의 문자 또는 문자열 제거         |
| `PadLeft()`                   | 특정 문자를 왼쪽에 채움                |
| `PadRight()`                  | 특정 문자를 오른쪽에 채움               |
| `StartsWith()`                | 특정 문자열로 시작하는지 여부             |
| `EndsWith()`                  | 특정 문자열로 끝나는지 여부              |

**문자열을 묶는 세 가지 표현 방법**

1. `+`로 연결
2. `String.Format()` : `String.Format("이름 : {0}{1}", lastName, firstName);`
3. 문자열 보간법 : `$"이름 : {lastName}{firstName}";`

**문자열을 비교하는 두 가지 방법**

1. `==`연산자 : 대소문자를 구분
2. `Equals();` : 대소문자 구분x, `if(s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase))` 또는 `if(string.Equals(s1,s2,StringComparison.InvariantCultureIgnoreCase)`

#### 25.3 StringBuilder 클래스

StringBuilder 클래스를 사용하려면 다음과 같이

```cs
> StringBuilder builder = new StringBuilder();
```

새로운 이름의 개체(인스턴스)를 생성해야 함. 출력하려면 `ToString()` 메서드로 문자열로 변환 후 사용 가능.

| **메서드**        | **설명**               |
| -------------- | -------------------- |
| `Append()`     | 문자열 추가               |
| `AppendLine()` | 문자열 추가하는데 끝에 `\r` 있음 |

***

### 26 예외 처리하기

#### 26.2 try-catch-finally 구문

```cs
try
{
	// 예외가 발생할 만한 코드 작성
}
catch
{
	// 예외가 발생할 때 처리해야 할 코드 블록
}
finally
{
	// 예외가 발생하거나 정상일 때 모두 처리해야 할 코드 블록
}
```

#### 26.3 Exception 클래스로 예외 처리하기

Exception: 닷넷에서 모든 예외에 대해 처리할 주요 기능을 담아 놓은 클래스

```cs
class ExceptionDemo
{
    static void Main()
    {
        try
        {
            int[] arr = new int[2];
            arr[100] = 1234;
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}
```

![](https://velog.velcdn.com/images/biomatrix117/post/82b0a5aa-a5da-48ad-bb2e-0c447eccdc0e/image.png)

`Exception` 클래스 형식의 변수인 ex에 예외 내용을 담으면 Message 속성으로 예외 내용을 알 수 있다. `Exception`은 다양한 예외 클래스(`ArgumentException`, `NullReferenceException`, `FormatException` 등)의 부모 클래스이다.

`FormatException`은 형식이 올바르지 않은 데이터가 사용될 때 발생하는 오류를 위한 Exception

#### 26.5 throw 구문으로 직접 예외 발생시키기

C#에서 throw 구문은 예외를 발생시키는 것.

```cs
void Divide(int a, int b)
{
    if (b == 0)
    {
        throw new DivideByZeroException("0으로 나눌 수 없습니다.");
    }
    Console.WriteLine(a / b);
}
```

`throw`를 사용하여 특정 조건에서 새로운 예외를 발생시킬 수 있습니다.

```cs
try
{
    int result = int.Parse("abc"); // 형식 오류 발생
}
catch (FormatException ex)
{
    Console.WriteLine("예외를 기록하고 다시 던짐.");
    throw; // 원래 예외를 재발생
}

```

`throw`를 사용하여 현재 발생한 예외를 다시 던질 수 있습니다. 이를 통해 예외 처리를 상위 호출 스택에 전달할 수 있습니다.

**throw와 throw ex의 차이**

```cs
catch (Exception ex)
{
    throw; // 원래 예외를 유지하고 상위로 전달
}
```

* 현재 예외의 원래 호출 스택 정보를 유지합니다.
* 디버깅 시 예외가 발생한 정확한 위치를 추적할 수 있습니다.

```cs
catch (Exception ex)
{
    throw ex; // 호출 스택 정보가 덮어써짐
}
```

* 예외 객체를 새로 던지면서 원래 호출 스택 정보를 덮어씁니다.
* 디버깅 시 원래 예외가 발생한 위치를 알기 어렵게 만듭니다.

***

### 27 컬렉션 사용하기

| **네임스페이스**                      | **클래스**                                                            |
| ------------------------------- | ------------------------------------------------------------------ |
| `System`                        | `Array` 클래스                                                        |
| `System.Collections`            | `Stack` 클래스, `Queue` 클래스, `ArrayList` 클래스                          |
| `System.Collections.Generic`    | `List<T>` 클래스, `LinkedList<T>` 클래스, `Stack<T>` 클래스, `Queue<T>` 클래스 |
| `System.Collections.Concurrent` | `ConcurrentStack<T>` 클래스, `ConcurrentQueue<T>` 클래스                 |

#### 27.3 Array 클래스

* Array.Sort() 배열을 정렬
* Array.Reverse() 배열을 역순으로 바꿈
* Array.ConvertAll() 배열을 다른 형식으로 변환

#### 27.5 Stack 클래스

* Count: 스택에 있는 데이터 개수 조회
* Push(): 스택에 데이터 저장
* Pop(): 스택에서 데이터 꺼내기
* Peek(): 스택 마지막 데이터 반환
* Clear(): 스택 비우기

#### 27.6 Queue 클래스

* Enqueue()
* Dequeue()

### 28 제네릭 사용하기

`Cup<T>` : Cup of T라고 발음한다. 형식 매개변수인 T에 따른 Cup 클래스의 개체를 생성한다.

제네릭: 넘어오는 데이터 형식에 따라 해당 개체 성격을 변경하는 구조

제네릭 컬렉션은 다른 데이터 형식을 추가할 수 없도록 형식 안정성을 적용한다. 고전적인 컬렉션 클래스와 달리 제네릭 컬렉션 클래스는 요소를 다룰 때 데이터 형식 변환 등 작업이 따로 필요하지 않다.

#### 28.2 Stack 제네릭 클래스 사용하기

```cs
> using Systemn.Collections.Generic;
> Stack<string> stack = new Stack<string>();
> stack.Push("First");
```

**제네릭 클래스 사용의 장점**

Stack이 아닌 `Stack<T>` 클래스를 사용하면 값형 데이터를 참조형 데이터로 변환하는 박싱 작업과 참조형 데이터를 값형 데이터로 변환하는 언방식 작업을 하지 않아도 되므로 성능이 향상된다.

#### 28.3 `List<T>` 제네릭 클래스 사용하기

```cs
> List<int> lstNumbers = new List<int<();
> lstNumbers.Add(30);
```

#### 28.4 Enumerable 클래스로 컬렉션 만들기

```cs
> Enumerable.Range(1,10)
RangeIterator { 1,2,3,4,5,6,7,8,9,10 }
> Enumerable.Repeat(100,5)
RepeatIterator { 100,100,100,100,100 }
```

#### 28.5 `Dictionary<T,T>` 제네릭 클래스 사용하기

```cs
> var data = new Dictionary<string, string>();
> data.Add("cs", "C#");
> foreach (var item in data)
. {
.    Console.WriteLine(item.Key, item.Value);
. }
```

```cs
// cs 키가 있으면 csharp 변수에 담음
data.TryGetValue("cs", out var csharp)

// 키 값이 있는지 없는지
data.ContainsKey("json")
```

### 29 널(null) 다루기

참조형 변수에 아무런 값을 설정하지 않음 null값과 빈 값(Empty, "")은 다르다

#### 29.2 null 가능 형식: `Nullable<T>` 형식

간단하게 설명하면, 값형 변수에는 원래 null 할당 못하고 에러 나는데, 할당할 수 있게 바꿔주는 거. bool을 예로 들면

* bool: true, false
* `Nullable<bool>`: true, false, null

줄여서 표현하면 bool?, int?처럼 데이터 형식 뒤에 ?(물음표) 기호 붙이면 됨.

`Nullable<T>` 형식이 제공하는 주요 멤버

* HasValue: 값이 있으면 true, null 값이면 false
* Value: 값 반환
* GetValueOrDefulat: 값 또는 기본값 반환

#### 29.3 null 값을 다루는 연산자 소개하기

**?? 연산자(null 병합 연산자)**

```cs
> nullValue = null;
> message = nullValue ?? "null일 경우 반환"
"null일 경우 반환"
```

```cs
> int? x = null;
> int y = x ?? default(int);
```

null 가능 형식과 default 키워드를 함께 사용한 예제.

```cs
> double? d = null;
> d?,ToString()
null
```

?. 연산자는 해당 값이 null인지 테스트

```cs
> List<string> list = null;
> num = list?.Count ?? 0;
```

`list?.Count ?? 0` 형태의 코드 익히면 좋다.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lazyartisan.gitbook.io/note/main-page/books/c/20-29.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
