[ C# 기초 ]
개념
Unity에서는 C#을 사용하므로, C#에 대해 보다 정확하고 기본적인 개념을 알고 가야 한다.
C#은 마이크로소프트에서 개발한 객체 지향 프로그래밍 언어이다. 자바와 구조가 비슷하고 C++의 기능을 혼합했기 때문에, 두 가지 언어를 배웠다면 C#을 좀 더 수월하게 공부할 수 있다.
객체 지향 프로그램이란 프로그램을 만들 때, 데이터와 메서드를 하나의 단위로 묶은 객체들의 모임으로 구현하는 것이다. 프로그램 제작에 사용될 객체들을 만들어 놓고, 필요할 때마다 이를 가져가 조립하는 방식이다.
객체 지향 프로그래밍은 이미 개발된 코드들을 재사용할 수 있어서, 개발에 드는 시간과 비용을 줄일 수 있다. 또한 수정이 필요할 때 객체 단위로 수정이 가능해 유지보수가 간편하고, 상속 기능을 이용해서 쉽게 확장할 수 있다.
C# 언어의 주요 특징은 다음과 같다.
1. .NET 프레임워크 사용
.NET 프레임워크는 Microsoft에서 출시한 개발 플랫폼이다. 다양한 프로그래밍 언어를 지원하고, 프로그램을 쉽게 개발할 수 있는 클래스 라이브러리와 API를 제공한다. .NET은 프로그램에 사용된 언어에 맞는 컴파일러를 사용해서 개발된 프로그램이 다양한 플랫폼에서 실행될 수 있도록 지원한다.
2. 객체 지향성
C#은 순수 객체 지향 언어로, 모든 것이 객체로 처리된다. 클래스, 상속, 캡슐화 등의 개념을 통해 코드의 중복을 최소화하고 유지보수를 용이하게 하여 개발 편의성을 높인다.
3. 가비지 컬렉션
.NET의 가비지 컬렉션 기능을 통해 쉽게 메모리 관리를 할 수 있다. 가비지 컬렉션은 메모리에서 더 이상 사용되지 않는 객체를 자동으로 찾아낸 뒤, 메모리를 해제하고 회수하여 메모리 누수를 방지한다.
4. 강력한 형식 시스템
C#의 모든 변수와 객체는 선언 시 명확한 타입을 갖게 된다. 이를 바탕으로 변수나 객체의 자료형이 정의된 형식에 맞는지 강력한 검사를 통해 안정성과 신뢰성을 높인다. 타입을 명확히 지정함으로써 코드의 가독성을 높이고, 실행 전 타입 관련 에러를 발견하고 미리 수정할 수 있게 도와 시간 단축 및 에러 가능성 감소의 장점이 있다.
구성
C#은 객체 지향 프로그래밍 언어로, 소프트웨어를 구성하는 각각의 객체를 생성하기 위한 클래스들의 집합으로 이루어져 있다. 이러한 클래스는 데이터(속성)와 기능(메서드)으로 구성되어 있다.
데이터(속성)는 로직, 알고리즘을 짜기 위해 준비되어야 하는 것으로, 객체의 상태를 나타내고 주로 레벨, 체력, 닉네임과 같은 것들이 된다. 데이터는 변수에 담기게 되는데, 종류로는 크게 단일 데이터, 배열/리스트, 구조체/클래스가 있다.
int level = 2;
string nickname = "식냥";
단일 데이터는 하나의 값을 저장하는 기본 데이터 타입이다. 여기서 int는 정수 값을 저장하는 데이터 타입으로, 변수 level에는 값 2가 저장된다. 이외에도 float, bool과 같은 데이터 타입이 있다.
int[] scores = new int[5]; //배열
List<string> names = new List<string>(); //리스트
배열/리스트는 쉽게 말해 단일 데이터가 여러 개 모인 것이다. 배열은 같은 타입의 여러 데이터를 고정된 메모리 공간에 순서대로 저장하는 구조이며, 리스트는 크기가 동적으로 변할 수 있는 배열과 유사한 구조이다.
//구조체
struct Point
{
public int X;
public int Y;
}
//클래스
public class Player
{
public string Name;
public int Score;
}
구조체/클래스는 여러 종류의 데이터와 메서드를 하나로 정의한 구조이다. 구조체는 변수에 할당될 때 값이 복사가 되는 값 타입이고, 클래스는 참조를 통해 접근하는 참조 타입이다. 이렇게 클래스 내부에 또 클래스가 들어가는 구조도 될 수 있다.
기능(메서드)은 객체가 수행할 수 있는 행동 또는 기능을 구현한다. 메서드는 클래스에 속한 함수로서, 클래스의 데이터를 처리하고 조작하는 로직을 포함한다. 알고리즘이 기능에 해당하며 공격하기, 움직이기, 경험치 증가와 같은 동작과 관련된 것들이 될 수 있다.
또 다른 클래스 구성 요소로는 생성자/소멸자가 있지만, 현재 단계에서는 데이터와 메서드에 대해서만 명확히 인지하고 있으면 된다.
[ 변수 ]
https://siknyang.tistory.com/5
https://siknyang.tistory.com/6
변수, 자료형에 대한 기초적인 내용은 위 게시글에서도 확인할 수 있다.
public int i = 5;
변수란 데이터를 저장해 두는 공간이다. 위 코드로 변수의 구성을 설명하면, 크게 4개로 나누어 설명할 수 있다.
접근제한자(Access)
public에 해당하는 부분이다. 액세스, 접근한다고 말하며, 데이터에 접근할 수 있는 권한을 결정한다. 주로 public, private, protected 3가지를 사용한다.
public class Car
{
public string model; //어디서든 접근 가능
private int speed; //Car 클래스 내부에서만 접근 가능
protected int wheelCount; //Car 클래스 및 상속받은 클래스에서 접근 가능
internal string engineType; //같은 어셈블리 내에서만 접근 가능
}
public은 '공개적인', '공공의'의 의미를 담고 있으며, 어디서든 접근할 수 있다. 모두에게 공유되는 만큼 상대적으로 다른 접근제한자들에 비해 보안이 약하다.
private는 '개인의', '사적인'의 의미를 담고 있으며, 해당 클래스 내에서만 접근이 가능하다. 3가지 중에서는 제일 보안이 강하다. 기본적으로는 pritvate로 생성하고 추후 공개하려는 것만 public으로 바꾸는 것이 좋다.
protected는 '보호된'의 의미를 담고 있으며, 허락한 상대만 접근할 수 있다. 클래스를 상속하면 부모 클래스와 자식 클래스의 관계도가 형성된다. 그중 자식 클래스가 상속 클래스가 되는데, 상속 클래스는 public을 포함하여 부모 클래스의 protected까지 접근이 가능하다. 하지만 상속 클래스도 부모 클래스 입장에서는 엄연한 외부 클래스이므로, private는 접근하지 못한다.
추가로 internal은 같은 어셈블리 내에서만 사용이 가능한 접근제한자다.
접근제한자는 자료형 앞에 위치하며, 즉 코드의 맨 앞에 위치한다. 접근제한자가 생략되어 있는 경우도 있는데, 이는 private이라는 접근제한자가 기본값으로 선언되어 암시적 생략이 되어있는 것이다. 하지만 되도록 표기를 해주는 것이 좋다.
자료형(Type)
int에 해당하는 부분이다. int, float, string과 같은 데이터의 종류를 나타낸다. 이러한 자료형의 명시를 통해 데이터 할당 가능 여부가 정해진다. 자료형과 데이터의 종류가 같아야만 할당이 가능하므로, 둘의 자료형을 통일시켜주어야 한다. 주로 많이 사용되는 것은 int, float, string, bool이 있다.
int는 정수를 표현한다. 뒤에 소수점 자리 없이 딱 떨어지는 숫자이다. 예를 들어 int i = 9;와 같은 코드로 표현할 수 있다.
float는 실수를 표현한다. 뒤에 소수점이 있는 숫자이다. 예를 들어 float f = 9.0f;로 표현할 수 있다.
int - long, float - double로 짝을 지어 외우면 편하다. 각각 같은 타입이지만 표현 범위가 다르다.
int i = 9;
float f = 9.0f;
int a = i / 2;
Console.WriteLine(a); //4
float b = f / 2;
Console.WriteLine(b); //4.5
같은 9인데 왜 둘을 구분할까? 하는 의문이 들 수 있지만, 둘은 분명한 차이가 있으며 자료형에 따라 연산 결과가 달라지기 때문에 반드시 구분해 주어야 한다.
둘 다 숫자 9이지만 2로 나눴을 때, int는 소수점까지 표현하지 못하므로 4가 출력된다. 하지만 float는 소수점까지 표현이 가능하기 때문에 온전하게 4.5가 출력된다.
string은 문자열이다. 문자와는 다른 개념으로, 문자는 char(character)이다. 문자열은 문자를 여러 개 나열한 것으로, 문자가 배열의 형태로 있는 것이다. string s = "spart"와 같은 코드로 표현할 수 있다.
bool은 논리값이다. 참, 거짓을 true, false 값으로 나타낸다. 주로 조건문에서 논리 연산으로 사용되며, bool isMonday = true;로 표현이 가능하다.
var은 초기화 값에 따라 자료형이 정해진다. 컴파일러가 인식하고 알아서 변수 타입을 지정해 주기 때문에 편리하게 사용할 수 있다. 초기화 값이 정수라면 int로, 문자열이라면 string으로 정해진다. 하지만 사용자가 코드를 봤을 때 한 번에 어떤 타입인지 알아보기가 힘들고, 반드시 선언과 동시에 초기화를 해주어야 하므로 적절하게 사용해야 한다.
▼ 이외 자료형
자료형 | 값 | 특징 | 기본값 | 크기 |
bool | true, false | false | 1 byte | |
string | 문자열 | " "로 감싸야 함 | null | |
char | 문자 | ' '로 감싸야 함 | '\0' | 2 byte |
sbyte | 8bit 정수 | -128 ~ 127 | 0 | 1 byte |
byte | 8bit 정수(부호 없음) | 0 ~ 255 | 0 | 1 byte |
short | 16bit 정수 | –32,768 ~ 32,767 | 0 | 2 byte |
ushort | 16bit 정수(부호 없음) | 0 ~ 65,535 | 0 | 2 byte |
int | 정수 | –2,147,483,648 ~ 2,147,483,647 | 0 | 4 byte |
uint | 정수(부호 없음) | 0 ~ 4,294,967,295 | 0 | 4 byte |
long | 64bit 정수 | –9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | 0 | 8 byte |
ulong | 64bit 정수(부호 없음) | 0 ~ 18,446,744,073,709,551,615 | 0 | 8 byte |
float | 실수 | 1.5E-45 ~ 3.4E+38 (7자리 유효) 0.0000001f 뒤에 f를 붙여야 함 |
0 | 4 byte |
double | 실수 | 5.0E-324 ~ 1.7E+308 (15자리 유효) 0.000000000000001d 뒤에 d를 붙이거나 아무것도 붙이지 않음 |
0 | 8 byte |
decimal | 실수 | ±1.0 x 10-28 ~ ±7.9228 x 1028 28-29개의 자릿수 |
0 | 16 byte |
정수 데이터를 할당하기 위해 사용할 수 있는 자료형으로는 sbyte, byte, short, ushort, int, uint, long, ulong이 있지만, 메모리 크기와 표현 범위에 따라 사용하는 자료형은 달라진다.
이렇게 자료형을 세분화하는 이유는 사용하려는 데이터에 맞는 표현 범위를 가진 자료형을 사용함으로써 메모리를 효율적으로 사용하고, 필요에 따라 자세한 소수점까지 표시하는 자료형을 사용해 데이터를 정확하게 표현할 수 있다. 또한 범위를 벗어나는 값을 할당하려고 했을 때 에러를 발생시켜 타입 안정성을 높이고, 세분화된 표현 범위와 기능을 활용해 코드의 오류 가능성을 낮출 수 있다.
변수명(Identifier)
//변수 만들고 값 할당
int number;
number = 7;
//변수 선언과 동시에 초기화
int number = 7;
변수명은 식별자, Identifier라고도 불린다. 변수명까지 적었을 때 변수를 선언한다, 생성한다라고 한다. 선언을 함으로써 메모리에 공간을 만들어 할당을 해주고, 이후 데이터를 넣어준다.
첫 번째 코드와 두 번째 코드의 결과는 같다. 하지만 둘은 엄연히 다른 코드라고 할 수 있다.
첫 번째 코드는 변수를 생성했을 때 사용할 수 없는 쓰레기 값이 들어있다. 이후 사용자가 명시적으로 실제 값을 할당하면 해당 값으로 대체된다. 두 번째는 값을 대체하는 과정 없이, 바로 사용자가 입력한 값을 할당해 준다.
이렇게 데이터를 할당하는 과정에서 두 코드는 명확한 차이가 있다.
변수명을 설정할 때는 몇 가지 규칙이 존재한다.
1. 키워드를 사용할 수 없다
C#에서 이미 사용되고 있는 예약어는 변수, 클래스, 함수의 이름으로 사용할 수 없다.
▼ 예약어 예시
abstract as base bool break byte case catch char checked class const
continue decimal default delegate do double else enum event explicit
extern false finally fixed float for foreach goto if implicit in int
interface internal is lock long namespace new null object operator out
override params private protected public readonly ref return sbyte sealed
short sizeof stackalloc static string struct switch this throw true try
typeof uint ulong unchecked unsafe ushort using virtual void volatile while
2. 맨 앞에는 영어와 언더바(_)만 사용한다
변수명으로 사용이 가능한 것은 영어, 언더바, 숫자이다. 하지만 숫자는 맨 앞에 올 수 없으며, 두 번째부터 올 수 있다. 영어는 대소문자를 구분한다.
3. 특수문자와 띄어쓰기는 사용할 수 없다
특수문자는 언더바를 제외하고는 사용할 수 없으며, 띄어쓰기도 사용할 수 없다.
한글은 사용 가능하지만, 협업할 때나 다른 프로그램에서의 호환성 문제가 발생할 수 있으므로 되도록 지양하는 편이 좋다.
변수명은 사용자가 원하는 대로 자유롭게 설정이 가능하다. 하지만 데이터가 뭘 뜻하는지 직관적으로 표시하도록 해야 한다. 변수명만 보고 데이터를 바로 알 수 있도록 변수명을 설정하는 것이 필요하다.
이러한 규칙들을 문서화해서 통용되는 법칙을 만든 것이 코드 컨벤션이다. 일종의 개발자들 사이의 약속으로, 이를 통해 코드의 가독성을 높이고 협업을 쉽게 하여 유지보수를 편하게 만든다.
1. 변수명
class GameCharacter
{
int charLevel;
string charName;
}
유니티에서 사용하는 코드 컨벤션은 카멜 케이스와 파스칼 케이스만 있다. 코드 컨벤션은 변수명 외에도 다른 이름에도 똑같이 적용된다.
- PascalCase: Unity, namespace, class, struct, method, enum, public 등
단어의 첫 글자마다 대문자로 사용한다. 예시로 ClassName, MethodName이 있다. - camelCase: non public, 함수 내부, 변수, 매개변수 등
맨 처음 단어의 앞글자만 소문자로 사용한다. 그다음 단어부터는 첫 글자를 대문자로 사용한다. 예시로 variableName, parameterName이 있다. - 대문자 약어: 예외
모든 글자가 대문자인 예외의 경우도 있다. 예시로 ID, HTTP 등이 있다.
int charLevel = 6; //캐릭터 레벨
if (charLevel > 4)
{
Console.WriteLine("퀘스트를 받아주세요.");
}
/*
초보 퀘스트 안내문 팝업 띄우기
4레벨부터 수락 가능
*/
2. 들여 쓰기
코드 블록을 들여 쓸 때는 Tap 1번 또는 띄어쓰기 4번으로 사용한다.
3. 중괄호 위치
중괄호는 새로운 줄에서 사용한다.
4. 빈 줄
서로 다른 내용의 코드 사이에는 한 줄 비워준다. 클래스나 메서드와 같은 코드 블록 사이에는 두 줄을 비워준다.
5. 주석
한 줄만 주석을 할 때는 //를 사용한다. 여러 줄을 주석 처리할 때엔 각 새로운 줄에서 /*와 */를 사용한다.
https://learn.microsoft.com/ko-kr/dotnet/csharp/fundamentals/coding-style/coding-conventions
이외 다양한 규칙들은 Microsoft 홈페이지에서 확인할 수 있다.
데이터(Value)
데이터는 값, Value라고도 불린다. 변수에 데이터를 넣을 때에는 '변수에 데이터를 할당한다'라고 한다. 자료형 파트에서 설명했듯이, 타입에 따라서 데이터를 할당할 수 있는지 여부가 결정되기 때문에 변수와 데이터의 자료형을 일치시켜 주어야 한다.
int num1, num2, num3;
num1 = num2 = num3 = 10;
string name1, name2;
name1 = "서영"; name2 = "식냥";
char first = 'a', second = 'b';
한 줄에서 두 개 이상의 변수에 값을 할당할 수 있다.
선언할 때와 선언 및 초기화는 쉼표(,), 할당할 때는 세미콜론(;)을 사용한다.
리터럴
리터럴은 프로그래밍에서 소스 코드 내에 고정된 값을 직접 표현하는 방법이다. 쉽게 설명하자면, 데이터가 어떤 자료형이고 어떤 값을 갖고 있는지 컴파일러가 바로 알 수 있도록 표현해 주는 것이다.
예를 들어 100이라는 데이터를 입력하려고 하는데, 이 100이 정수 100인지, 실수 100.0인지, 문자열 "100"인지 모르기 때문에, 이를 한 번에 알 수 있게 표현하는 것이다.
byte age = 22;
int view = 513854;
long person = 8105127009;
정수 리터럴은 상수 값을 그대로 표현한다.
float speed = 20.35f;
double high = 63.2943;
decimal pie = 3.141592m;
부동소수점 리터럴은 소수점을 포함한 상수 값으로 표현한다.
char firstName = '김';
char secondName = '서';
char thirdName = '영';
문자 리터럴은 작은따옴표(' ')로 표현한다.
string corporation = "스파르타코딩클럽";
string routine = "매일 TIL을 작성하기.";
string game = "steam";
문자열 리터럴은 큰따옴표(" ")로 표현한다.
이외에도 각 타입에 맞는 다양한 리터럴이 존재한다.
[ 형변환 ]
개념
서로 자료형이 다른 두 변수 간의 연산이나 할당을 위해, 두 변수의 자료형을 일치시켜 주는 것이다.
명시적 형변환
long num1 = 3;
int num2 = (int)num1;
형변환을 위해 가시적인 코드를 작성해야 한다. 방법은 할당하려는 변수 앞에 변환하려는 (자료형)을 입력한다.
암시적 형변환
//1. 작은 데이터 → 큰 데이터
int level = 7;
long newLevel = (long)level;
//int보다 long이 더 표현 범위가 넓어서 int가 long에 포함됨
//2. 리터럴 값 대입
float speed = 10;
//int인 10은 10.0으로도 표현할 수 있으므로 float로 대체
//3. 정수형 - 부동소수점 연산
int age1 = 22;
float age2 = 33.23f;
float sum = age1 + age2;
//int인 22는 22.0으로도 표현할 수 있으므로 flaot와 연산 가능
특정 상황에서 자동으로 형변환이 일어나기 때문에, 생략이 가능하다. 간결하게 코드를 작성할 수 있다는 장점이 있지만, 추후 암시적 형변환이 된 코드를 사용할 때 생략된 부분까지 고려를 해야 한다.
[ 출력 및 입력 ]
Console.WriteLine("Hello!");
Console.Write("My name is ");
Console.Write("seoyeong.");
//출력결과
Hello!
My name is seoyeong.
Console.WriteLine()은 출력 후 줄 바꿈을 하고, Console.Write()는 줄 바꿈을 하지 않는다.
Console.Write("이름을 입력해 주세요: ");
string name = Console.ReadLine();
Console.WriteLine("제 이름은 " + name + "입니다.");
//출력결과
이름을 입력해 주세요: 김서영
제 이름은 김서영입니다.
Console.ReadLine()는 사용자의 입력을 받는다. 위 코드에서는 콘솔창에서 입력한 데이터가 변수에 string 타입으로 저장된다.
[ 주석 ]
https://siknyang.tistory.com/2
주석 및 이스케이프 시퀀스에 대한 전반적인 내용은 위 게시글에서 확인할 수 있다.
주석 단축키를 이용하면 여러 줄을 주석 처리할 때 빠르고 편리하게 이용할 수 있다.
주석을 추가하려면 선택된 줄이나 커서가 위치한 줄에서 Ctrl + K & Ctrl + C를 누른다.
주석을 제거하려면 선택된 줄이나 커서가 위치한 줄에서 Ctrl + K & Ctrl + U를 누른다.
[ 회고 ]
사전 캠프 당시에 기초 자료를 통해 알고 있던 내용이었지만, 더 심화된 내용을 배우게 되니 C#에서 코드가 어떤 구조를 가지고 있고, 이를 어떻게 사용하면 좋을지 갈피가 더 잘 잡히게 됐다.
공부를 하면서 정말 많은 자료를 찾아봤었는데, 자주 등장했던 단어가 "객체 지향"이었다. 당시에는 내가 갖고 있던 문제점을 해결하고 그 궁금증만을 해결하기 위해 객체 지향의 정의까지는 찾아보지 않았지만, 이번에 C# 언어에 대해서부터 공부하면서 객체 지향 프로그래밍이라는 것에 대해 잘 알게 되었다. 그로 인해 왜 모든 스크립트의 기본 구조는 클래스로 되어있고, 매번 다른 클래스를 참조하여 사용하는지 이유를 알게 되었다.
그 외 주석에도 단축키가 있는 줄은 몰랐다. 이것 말고도 많은 단축키가 있을 텐데, 알아놓으면 편할 것 같아서 언제 한 번 날 잡고 유용하게 사용할 수 있을 법한 단축키들을 찾아서 정리해 봐야겠다.
'Coding > C#' 카테고리의 다른 글
[내일배움캠프 8일차 TIL] 비트 연산자, 시프트 연산, 단축 평가, 비트 플래그, 2진법 (0) | 2024.04.24 |
---|---|
[내일배움캠프 7일차 TIL] 배열, 컬렉션, 메서드, 구조체, 조건문, 반복문 (0) | 2024.04.23 |
C# 배열 생성 및 데이터 저장, 접근, 배열 리터럴, 인덱스 (0) | 2024.04.13 |
C# 반복문 연습 문제 (0) | 2024.04.13 |
C# 반복문 for, while, do while, break, continue (0) | 2024.04.13 |