C# 기본 지식

타입 캐스팅

int a = 100;
short b = (short)a;

float c = a;
int d = (int)c;

변수를 저장하는 큰 상자를 작은 상자에 넣기위해 캐스팅을 한다.

큰상자에 작은 상자를 넣는 것은 상관없지만, 작은 상자에 큰 상자를 넣는 것은 안된다.

 

 

 

 

문자열 입출력

//string >> int

string input = Console.ReadLine();
int number = int.Parse(input);
Console.WriteLine(number);

Console.ReadLIne으로 입력받은 값은 string값으로 출력된다.

여기에서 console.readline은 콘솔창에 엔터를 누를 때 까지 기다린다는 의미이다.

만약 숫자를 입력 후 숫자로 저장받고 싶다면 int.Parse()를 사용한다.

Convert.Toint32(Console.ReadLIne()); 로도 정수 변환이 가능하다.

 

 

둘 다 문자열을 정수로 변환하지만, int.Parse()는 반드시 string을 입력받고, Convert.Toint32()는 다양한 형식을 입력받을 수 있다.

 

 

//int >> string

int a = 1;
int b = 2;

string message = string.Format("a는 {0} b는 {1}", a, b);
Console.WriteLine(message);

// 또는
string message = $"a는 {a}, b는 {b}";
Console.WriteLine(message);

일반적으로 string.Format형식보다 $" " 형식을 선호함

 

 

 

 

switch case 와 enum 타입

 

switch case문의 case에는 변수를 넣을 수 없고 고정된 값(상수)만 가능하다.

가독성은 좋지만 if문 보다 제한되는 상황이다 보니, case에 들어가는 상수는 의미를 갖는 enum형을 넣는 것이 좋다.

 

enum형은 변수가 수십개씩 늘어나다 보면 변수명이 겹치지않게 신경쓰이는 경우를 해결해준다.

위 상황처럼 임의의 문자열에 상수를 순서대로 부여해서 switch case에 사용할 수도 있다.

 

enum타입에서 꺼내온 변수들은 정수가 아니라 enum타입이기 때문에

case에 쓸 때는 바로 변수명을 입력하는게 아니라 (int)를 붙여줘야 한다.

 

그리고 바로 사용하면 enum에서 가져온 지 모르니까 최종적으로 (int)enumType.문자열을 해야한다.

 

 

즉, enum(열거형)은 기본적으로 상수 값을 그룹화하는 특별한 타입이라고 말할 수 있다.

각 enum 멤버는 상수이며, 프로그램에서 변경할 수 없다.

 

 

 

 

ref와 out

static void Divide(int a, int b, out int result1, out int result2)
{
	result1 = a/b;
    result2 = a%b;
}

static void main()
{
	int num1 = 10;
    int num2 = 3;
    
    int result1;
    int result2;
    Divide(10, 3, out result1, out result2);
}

C#에는 포인터 개념이 없는 대신 ref를 이용해서 값의 참조를 할 수 있다.

 

보통 함수에서 받은 매개변수를 복사하기 때문에 실제 값은 변화가 없지만, ref를 사용하면 실제로 값을 변화시킨다.

out은 함수에서 계산한 결과를 해당 변수에 저장하겠다는 의미이다.

 

 

 

 

오버로딩

static int Add(int a, int b, int c=0, float d=1.0f)
{
	return a+b+c;
}

static void main()
{
	class.Add(1, 2, d:2.0f)
}

 

 

 

 

구조체

struct Mage {
    public int hp;
    public int attack;
}

나중가면 함수에 넣어야 할 매개변수가 수십개는 되는데, 변수를 하나하나 함수에 다 넘길 필요 없이

대장 구조체 하나만 넘기면 간단하니 구조체를 사용한다.

그냥 변수 담는 바구니임

 

 

 

 

클래스

 

함수를 중심으로 하는 절차(프로시저)지향, 클래스 중심의 객체지향 프로그래밍이 있다.

절차 지향으로 프로그래밍을 하면 함수 안에 함수를 호출하는 등 상속 관계가 엉망이 되서 유지보수가 힘들어진다.

 

클래스 중심의 객체 지향으로 관리하게 되면 해당 객체만 고치면 되니 유지보수가 편하다.

클래스는 붕어빵 틀 같은 설계도 개념이라 생각하자.

 

 

class는 ref 참조이므로,

main에서 함수의 파라미터 값으로 인스턴스를 넣어줘서 값 변경 시

ref로 굳이 명시하지 않아도 실제 인스턴스 값이 변한다.

 

하지만 struct는 복사이므로 값이 변하지 않는다.

 

 

 

 

생성자

 

생성자는 클래스 이름() 만 쓰고 아무것도 쓰지 않는다.

처음 객체를 생성할 때 초기화에 사용한다.

 

보통 Class name = new Class(); 형식으로 생성자를 통해 초기화하는데

public Knight Clone()
{
	
    Knight kight = new Knight();
    knight.hp = hp;
    knight.attack = attack;
    return knight;
}

이런 형식으로 함수로 초기화할 수도 있다.

Knight.Clone

 

 

앞서 말했던 오버로딩이 가능하다.

초기화해야 할 변수들이 나중가면 몇십개씩 되는데 이럴 때 사용할 수 있다.

public Knight(int hp) : this()
{
    this.hp = hp;
}

public Knight(int hp, int attack) : this()
{
    this.hp = hp;
    this.attack = attack;
}

 

여기에서 this()는 매개변수로 받지 않은 나머지 필드들은 처음 만들었던 생성자에 초기화된 값을 사용한다는 의미이다.

 

 

 

 

static

 

static이란 알다싶이 정적이란 의미인데, 그래서 뭐가 정적이냐고 물어볼 수 있다.

 

각각의 인스턴스에 따라 필드는 달라질 수 있다.

만약 필드가 static 으로 선언된다면 전역변수로 객체들이 값을 공유하므로, 인스턴스에 따라 다른 값이 아니라 class에 따라 값을 가질 수 있게 된다.

간단하게 인스턴스별로 존재하는 것이 아니라 클래스에 오로지 한개만 존재한다.

 

클래스에 종속되는가, 클래스의 인스턴스에 종속되는가 차이임

 

 

 

클래스 내의 함수에 붙는 static은 애초에 클래스에 종속이든 아니든 함수를 바꿀 수 없는데, 이게 무슨 의미를 갖나면

static으로 선언된 함수의 내부에서는 외부의 필드를 건드릴 수 없다.

 

왜냐하면 static으로 선언된 함수는 결국 클래스의 공용함수인데

공용함수에서 개개인의 인스턴스에 있는 고유 필드에 접근할 수 없기 때문이다.

 

모든 인스턴스마다 필드값이 다를 수 있는데

이 공용함수가 어떤 인스턴스를 참조해야 될지를 알 수 없다.

그래서 static 함수 안에서는 static으로 선언된 변수만 연산할 수 있다.

 

 

오해하면 안되는게 static을 붙여도 일반 인스턴스에 접근 가능하다.

하지만 접근하기 위해서 함수 안에 새로 생성자를 통해 인스턴스를 생성하고 그 인스턴스의 필드에 접근한다.

 

static은 클래스에 종속됐으므로 클래스.static 함수로 바로 호출 가능하지만, 다른 함수는 인스턴스.함수로 접근해야 한다.

 

 

 

 

string

string name = "Harry Potter";

// 1. 찾기
bool found = name.Contains("Harry");
int index = name.IndexOf('z'); // -1 반환

// 2. 변형
name = name + " Junior";
string lowerCaseName = name.ToLower();
string upperCaseName = name.ToUpper();
string newName = name.Replace('r', 'l');

// 3. 분할
string[] names = name.Split(new char[] { ' ' });
string substringName = name.Substring(5);

 

 

 

 

 


 

레퍼런스

https://www.inflearn.com/course/%EC%9C%A0%EB%8B%88%ED%8B%B0-mmorpg-%EA%B0%9C%EB%B0%9C-part1/dashboard