개요)
이번에 학교에서 Unity로 게임을 만들어보는 수업을 듣게 되었다. Unity가 게임을 만드는 프로그램이라는 것은 알고 있었지만 크게 관심있는 분야는 아니었기에 자세히는 몰랐다. Unity에서는 C#이 사용된다 하였고 C#을 사용해보지는 않았지만 여러 프로그래밍 언어를 사용해보면서 이름은 다르지만 어느정도는 서로 비슷한 문법을 지니고 있는 것을 느꼈기에 관련 내용을 찾아보았고 나중에 필요할 때 사용하기 위해 한 번에 정리해놓으려 한다.
목차)
- C#이란?
- 변수
- 연산자
- 클래스
- 조건문
- 반복문
- 배열(Array), 컬렉션(Collection)
- 주석
- MSDN(Microsoft Developer Network)
1. C#이란?
C#은 마이크로소프트에서 2000년도에 개발된 객체 지향 프로그래밍(Object Oriented Programming) 언어로써 닷넷(.NET) 프레임워크의 한 부분으로 만들어졌다. 1995년에 나온 Java를 보고 마이크로소프트의 Java를 만들고자 하는 프로젝트를 통해 개발되었다. 확장자는 cs이고 유니티 엔진의 기본 개발 언어이다.
2. 변수
▶ 자료형
C#의 자료형은 아래와 같다.
자료형 | 설명 | 크기(바이트) | 기본값 |
var | 값에 따라 타입이 자동으로 매칭 | 값에 따라 다름 | - |
bool | 참, 거짓 | 1 | false |
byte | 정수 | 1 | 0 |
sbyte | 부호 있는 정수(signed) | 1 | 0 |
short | 정수 | 2 | 0 |
ushort | 부호 없는 정수(unsigned) | 2 | 0 |
int | 정수 | 4 | 0 |
uint | 부호 없는 정수(unsigned) | 4 | 0 |
long | 정수 | 8 | 0 |
ulong | 부호 없는 정수(unsigned) | 8 | 0 |
char | 유니코드 문자 | 2 | '\0' |
float | 실수 | 4 | 0.0F |
double | 실수 | 8 | 0.0D |
decimal | 실수 | 16 | 0.0M |
▶ 변수 선언
변수 선언은 다음과 같은 형태로 한다. 변수 이름은 대부분의 다른 프로그래밍 언어와 같이 숫자로 시작할 수 없고 예약어를 사용할 수 없다. 변수를 초기화하지 않고 사용하려 하면 오류가 발생한다.
int v1; // 선언만 -> 사용하려고 하면 오류 발생함
int v2 = 10; // 선언 + 초기화
int v3 = default; // 기본값으로 초기화
▶ 형 변환(암시적 형 변환, 명시적 형 변환)
암시적 형 변환이란 컴파일러가 자동으로 형을 변환해 주는 것이고 다음과 같은 코드에서 발생한다. int형 변수 v1과 float형 변수 v2의 연산을 위해 v1이 float형으로 변환되어 연산되는 것이다.
namespace ConsoleApp1
{
internal class Program
{
public static void Main(string[] args)
{
int v1 = 3;
float v2 = 0.5f;
Console.WriteLine(v1+v2);
}
}
}
반면 명시적 형 변환은 사용자가 직접 필요에 맞게 형 변환을 하는 것을 말하고 그 방법은 다음과 같다.
// (변환할 자료형)변수명
int v = 3;
float v2 = (int)v;
namespace ConsoleApp1
{
internal class Program
{
public static void Main(string[] args)
{
float v1 = 3.5f;
int v2 = (int)v1;
Console.WriteLine("원래 실수 v1의 값 : " + v1);
Console.WriteLine("정수로 형 변환 : " + (int)v1);
Console.WriteLine("v2의 값 : " + v2);
}
}
}
▶ 오버플로(Overflow)
C언어에서는 변수의 범위를 초과하는 값이 저장되는 경우 오버플로된 값이 저장되었지만 C#에서는 오류가 발생한다.
3. 연산자
▶ 산술 연산자
C#의 산술 연산자는 아래 표와 같다.
연산자 | 설명 | 예시 |
+ | 덧셈 | 10 + 20 |
- | 뺄셈 | 20 - 10 |
* | 곱셈 | 10 * 20 |
/ | 나눗셈(몫) | 10 / 3 (결과는 3.333...이 아닌 3) |
% | 나머지 | 10 % 3 (결과는 1) |
namespace ConsoleApp1
{
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine("덧셈 10 + 20 : " + (10 + 20) );
Console.WriteLine("뺄셈 20 - 10 : " + (20 - 10) );
Console.WriteLine("곱셈 10 * 20 : " + (10 * 20) );
Console.WriteLine("나눗셈(몫) 10 / 3 : " + (10 / 3));
Console.WriteLine("나머지 10 % 3 : " + (10 % 3) );
}
}
}
▶ 증감 연산자
증감 연산자는 C언어에서 보던 것과 동일하다. 연산자가 피연산자 앞에 위치하면 증감 연산을 먼저 수행한 뒤 나머지 연산을 수행하고, 피연산자 뒤에 위치하면 모든 연산을 끝낸 뒤에 증감 연산을 수행한다.
연산자 | 설명 | 예시 |
++ | 1 증가 | a++, ++a |
-- | 1 감소 | a--, --a |
namespace ConsoleApp1
{
internal class Program
{
public static void Main(string[] args)
{
int a = 1, b = 2;
Console.WriteLine(a++); // 1이 출력되고 1이 증가 => 1
Console.WriteLine(++a); // 1이 증가되고 출력 => 3
Console.WriteLine(b--); // 2가 출력되고 1이 감소 => 2
Console.WriteLine(--b); // 1이 감소되고 출력 => 0
}
}
}
▶ 관계 연산자
관계 연산자도 다른 프로그래밍 언어에서 보던 것과 다를 바 없다. 코드는 생략한다.
연산자 | 예시 | 설명 |
> | a > b | a가 b보다 크면 참, 아니면 거짓 |
< | a < b | a가 b보다 작으면 참, 아니면 거짓 |
>= | a >= b | a가 b이상이면 참, 아니면 거짓 |
<= | a <= b | a가 b이하이면 참, 아니면 거짓 |
== | a == b | a와 b가 같으면 참, 아니면 거짓 |
!= | a != b | a와 b가 다르면 참, 아니면 거짓 |
▶ 논리 연산자
논리 연산자는 C언어와 동일하게 기호를 사용한다. and, or, not을 사용하는 Python과는 다르다. 코드는 생략한다.
연산자 | 설명 | 예시 |
&& | AND | A && B(A와 B가 모두 true여야만 true) |
|| | OR | A || B(둘 중 하나만 true여도 true) |
! | NOT | true였다면 false로, false였다면 true로 |
4. 클래스
C#은 객체 지향 프로그래밍 언어이므로 클래스와 인스턴스 개념이 존재한다. 집을 짓는다고 하면 집의 설계도는 클래스이고 실제로 지은 집은 인스턴스(객체)가 되는 것이다.
▶ 클래스 선언
클래스는 속성(property), 생성자(constructor), 소멸자(Destructor), 메서드(method)로 구성된다. 속성은 멤버 변수, 메서드는 함수라고 부르기도 한다.
class Car
{
// 속성(Property)
private string Name;
private int Price;
// 생성자
public Car()
{
Console.WriteLine("자동차가 생성되었습니다.");
}
// 소멸자
~Car()
{
Console.WriteLine("자동차가 소멸되었습니다.");
}
// 메서드(Method)
public void Go()
{
Console.WriteLine("자동차가 출발합니다.");
}
public void Stop()
{
Console.WriteLine("자동차가 멈춥니다.");
}
}
▶ 인스턴스화
클래스를 객체로 구현하기 위해서는 new 키워드를 사용한다(역시 프로그래밍 언어는 비슷비슷하다..). 아래 코드는 위 클래스를 객체로 구현하여 Go() 메서드를 호출하고 있다.
class Program
{
public static void Main(string[] args)
{
{
Car c1 = new Car();
c1.Go();
}
}
}
▶ 오버로딩(Overloading)
C#은 객체 지향 프로그래밍 언어이므로 오버로딩 개념이 존재한다. 이는 이름이 동일한 메서드를 여러 개 중복 정의하는 것인데 주의할 점으로는 메서드의 매개 변수의 타입과 개수가 일치하면 안된다는 것이다. 아래 코드는 위의 Car 클래스의 생성자를 오버로딩 한 것이다.
// 생성자
public Car()
{
Console.WriteLine("자동차가 생성되었습니다.");
}
public Car(string Name)
{
Console.WriteLine(Name + "자동차가 생성되었습니다.");
}
.
.
.
public static void Main(string[] args)
{
{
Car c1 = new Car();
Car c2 = new Car("Sonata");
}
}
▶ 상속
C#은 객체 지향 프로그래밍 언어이므로 상속 개념 또한 존재한다. 상속 받는 클래스는 자식 클래스, 상속 되는 클래스는 부모 클래스라 한다. 상속 형식은 다음과 같다.
class 자식 클래스: 부모 클래스
{
...
}
아래 코드는 Car 클래스를 상속 받는 RedCar 클래스를 선언하여 인스턴스화 하는 과정이다. RedCar에는 Go 메서드를 선언하지 않았지만 부모 클래스인 Car 클래스에 Go 메서드가 있기 때문에 메서드가 상속되어 사용이 가능한 것이다.
class Car
{
// 속성(Property)
private string Name;
// 생성자
public Car()
{
Console.WriteLine("자동차가 생성되었습니다.");
}
public Car(string Name)
{
Console.WriteLine(Name + "자동차가 생성되었습니다.");
}
// 메서드(Method)
public void Go()
{
Console.WriteLine("자동차가 출발합니다.");
}
}
class RedCar: Car
{
public RedCar()
{
Console.WriteLine("빨간색 자동차가 생성되었습니다.");
}
}
class Program
{
public static void Main(string[] args)
{
{
Car c1 = new Car();
RedCar c2 = new RedCar();
c2.Go();
}
}
}
위 코드의 실행 흐름은 아래와 같다.
- c1 객체 생성
- Car() 생성자 호출
- c2 객체 생성
- Car() 생성자(부모 생성자) 호출
- RedCar() 생성자(자식 생성자) 호출
- c2.Go() 메서드 호출
▶ 오버라이딩(Overriding)
오버라이딩이란 부모 클래스에 있는 메서드를 자식 클래스에서 재정의하는 것을 말한다. 앞서 c2 객체는 Go() 메서드가 없지만 부모 클래스인 Car 클래스에 Go() 메서드가 존재했기에 사용이 가능했다. 이 Go() 메서드를 자식 클래스인 RedCar 클래스에서 재정의하게 되면 이제 부모 클래스의 Go() 메서드가 아닌 자식 클래스의 Go() 메서드가 호출되게 된다.
(동일)
.
.
.
class RedCar: Car
{
public RedCar()
{
Console.WriteLine("빨간색 자동차가 생성되었습니다.");
}
// 메소드 오버라이딩(Method Overriding)
public void Go()
{
Console.WriteLine("빨간색 자동차가 출발합니다.");
}
}
.
.
.
(동일)
▶ 접근 제한자
C#의 접근 제한자는 다음 표와 같다.
접근 제한자 | 설명 |
public | 어느 곳에서든 자유롭게 사용 가능 |
private | 선언된 범위 내에서만 사용 가능 |
internal | 선언된 프로젝트 내에서만 사용 가능 |
protected | 상속받은 자식의 클래스에서만 사용 가능 |
클래스의 접근 제한자를 생략하면 기본값은 internal이다. 클래스의 속성, 메서드의 접근 제한자를 생략하면 기본값은 private이다. C# 역시 클래스의 속성(Property)은 private으로 선언하고 Setter()과 Getter() 메서드를 정의하여 사용하는 방법을 사용한다.
namespace ConsoleApp1
{
class Person
{
// 속성(Property)
string name; // 접근 제한자 생략했으므로 private
// Setter()
public void SetName(string name)
{
this.name = name;
}
// Getter()
public string GetName()
{
return this.name;
}
}
internal class Program
{
public static void Main(string[] args)
{
{
Person p1 = new Person();
p1.SetName("John");
Console.WriteLine(p1.GetName());
}
}
}
}
5. 조건문
C#의 조건문은 C언어의 조건문과 동일하다. if, if ~ else, if ~ else if ~ else, switch문이 있다. C언어와 다른 점이라면 조건문에는 반드시 true 또는 false형태의 값이 와야 한다는 것이다. C언어에서는 0은 거짓(false), 0외의 수는 참(true)으로 처리됐지만 C#에서는 bool 타입 외의 값이 조건문에 오면 오류가 발생하게 된다.
if (조건문) {
...
}
if (조건문) {
...
} else {
...
}
if (조건문) {
...
} else if (조건문) {
...
} else {
...
}
switch ~ case 문도 C언어와 동일하다.
public static void Main(string[] args)
{
{
int a = 95;
switch (a/10)
{
case 10:
Console.WriteLine("100점");
break;
case 9:
Console.WriteLine("90점 ~ 99점");
break;
case 8:
Console.WriteLine("80점 ~ 89점");
break;
default:
Console.WriteLine("재시험");
break;
}
}
}
6. 반복문
C#의 반복문은 우선 C언어와 동일하게 do ~ while, while, for문이 있고 C언어에는 없는 foreach문도 존재한다.
▶ do ~ while
do {
// 실행 코드
// 처음 1번은 무조건 실행
} while (조건식); // 세미콜론 필수
▶ while
while (조건식) {
// 실행 코드
}
▶ for
// 초기화 부분에서 변수 초기화 가능(C언어와의 차이점)
for (int i=i ; i<=10 ; i++) {
Console.WriteLine(i);
}
▶ foreach
public static void Main(string[] args)
{
int[] arr = { 1, 2, 3 };
foreach (int i in arr)
{
Console.WriteLine(i);
}
}
7. 배열(Array), 컬렉션(Collection)
▶ 배열(Array)
C#에서 배열을 선언하는 방법은 아래와 같다.
// 방법 1)
int[] arr1 = new int[5];
// 방법 2)
int[] arr2 = new int[] {1, 2, 3, 4, 5};
// 방법 3)
int[] arr3 = {1, 2, 3, 4, 5};
배열의 인덱스는 C언어와 동일하게 0부터 시작하고 배열의 범위를 벗어나면 인덱스 에러가 발생한다.
▶ 컬렉션(Collection)
컬렉션이란 다양한 자료 구조의 모음으로 System.Collections 네임스페이스에 포함된 컬렉션 클래스에는 ArrayList, Queue, Stack, Hashtable 등이 있다.
▷ ArrayList
ArrayList는 배열과 유사한 데이터 묶음을 관리하는 클래스이다. 단, 생성자가 호출될 때 크기를 미리 지정하지 않아도 되고 여러 자료형의 값을 저장할 수 있다.
using System.Collections;
namespace ConsoleApp1
{
internal class Program
{
public static void Main(string[] args)
{
ArrayList al = new ArrayList();
// Add() 메서드로 추가
al.Add(10);
al.Add("Hello C#");
al.Add(new int[] {1,2,3,4,5});
al.Add(true);
foreach(var item in al)
{
Console.WriteLine(item);
}
Console.WriteLine();
// Remove() 메서드로 삭제
al.Remove(10);
foreach (var item in al)
{
Console.WriteLine(item);
}
}
}
}
▷ Queue
Queue는 먼저 들어온 값이 먼저 나가는 자료구조이다.
using System.Collections;
namespace ConsoleApp1
{
internal class Program
{
public static void Main(string[] args)
{
Queue queue = new Queue();
// Enqueue() 메서드로 추가
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
foreach (var item in queue)
{
Console.WriteLine(item);
}
Console.WriteLine();
// Dequeue() 메서드로 삭제
while (queue.Count > 0)
{
queue.Dequeue();
}
Console.WriteLine("남은 개수 : " + queue.Count);
}
}
}
▷ Stack
Stack은 Queue와는 달리 먼저 들어온 값이 나중에 나가는 자료구조이다.
using System.Collections;
namespace ConsoleApp1
{
internal class Program
{
public static void Main(string[] args)
{
Stack st = new Stack();
// Push() 메서드로 추가
st.Push(1);
st.Push(2);
st.Push(3);
foreach (var item in st)
{
// 1, 2, 3순으로 추가했으므로 3, 2, 1순으로 출력
Console.WriteLine(item);
}
// Pop() 메서드로 삭제
while(st.Count > 0)
{
st.Pop();
}
Console.WriteLine("남은 개수 : " + st.Count);
}
}
}
8. 주석
C#에서의 주석은 C언어와 동일하게 //와 /* */가 있다.
// 이 주석은 한 줄씩 주석으로 처리하고 싶을 때 사용한다.
/*
이 주석은 여러 줄을 동시에
주석으로 처리하고 싶을 때
사용한다.
*/
9. MSDN(Microsoft Developer Network)
MSDN은 개발 문서나 환경 등에 대한 정보를 획득할 수 있는 사이트이다. Microsoft에서 제작하고 운영하는 것으로 MS에서 제작한 콘텐츠는 물론 다른 여러 소식 등도 확인 할 수 있다.
MSDN에서 C#에 대한 내용을 확인하려면 아래의 링크로 접속하면 된다.