|
|
## 기본 문법
|
|
|
---
|
|
|
|
|
|
### **기본 자료형**
|
|
|
#### **정수형**
|
|
|
| **자료형** | **크기** | **기본값** | **범위** | **.NET Framework 형식** |
|
|
|
| -------- | -------- | -------- | -------- | -------- | -------- |
|
|
|
| `sbyte` | 1byte | 0 | 0~255 | System.SByte |
|
|
|
| `byte` | 1byte | 0 | -128~127 | System.Byte |
|
|
|
| `short` | 2byte | 0 | -32,768~32,767 | System.Int16 |
|
|
|
| `ushort` | 2byte | 0 | 0~65,535 | System.UInt16 |
|
|
|
| `int` | 4byte | 0 | -2,147,483,648~2,147,483,647 | System.Int32 |
|
|
|
| `uint` | 4byte | 0 | 0~4,294,967,295 | System.Int32 |
|
|
|
| `long` | 8byte | 0L | -9,223,372,036,854,775,808~9,223,372,036,854,775,807 | System.Int64 |
|
|
|
| `ulong` | 8byte | 0 | 0~18,446,744,073,709,551,615 | System.UInt64 |
|
|
|
|
|
|
#### **실수형**
|
|
|
| **자료형** | **크기** | **기본값** | **범위** | **.NET Framework 형식** |
|
|
|
| -------- | -------- | -------- | -------- | -------- | -------- |
|
|
|
| `float` | 4byte | 0.0F | 0~255 | System.Single |
|
|
|
| `double` | 8byte | 0.0D | -128~127 | System.Double |
|
|
|
| `decimal` | 162byte | 0.0M | -32,768~32,767 | System.Decimal |
|
|
|
|
|
|
#### **문자형**
|
|
|
| **자료형** | **크기** | **기본값** | **범위** | **.NET Framework 형식** |
|
|
|
| -------- | -------- | -------- | -------- | -------- | -------- |
|
|
|
| `char` | 2byte | ‘\0’ | U+0000~U+FFFF | System.Char |
|
|
|
| `string` | | | 문자열 | System.String |
|
|
|
|
|
|
#### **논리형**
|
|
|
| **자료형** | **크기** | **기본값** | **범위** | **.NET Framework 형식** |
|
|
|
| -------- | -------- | -------- | -------- | -------- | -------- |
|
|
|
| `bool` | | false | true, false | System.Boolean |
|
|
|
|
|
|
### **var 형식**
|
|
|
변수의 형식을 반드시 지정해줄 필요 없이 **var 형식**을 사용하여 값의 종류에 따라 컴파일러가 유추하여 사용한다.
|
|
|
```javascript
|
|
|
var i = 3; // int
|
|
|
var d = 3.0; // double
|
|
|
var s = "value"; // String
|
|
|
|
|
|
Console.WriteLine(i.GetType().FullName()); // 출력 결과 : System.Int32
|
|
|
Console.WriteLine(i.GetType().FullName()); // 출력 결과 : System.Double
|
|
|
Console.WriteLine(i.GetType().FullName()); // 출력 결과 : System.String
|
|
|
```
|
|
|
|
|
|
### **Nullable 형식**
|
|
|
**Nullable 형식**은 내부 형식의 값 이외에도 `null` 값을 저장할 수 있는 형식이다. *Nullable<T>*과 같이 구조체로 표기하지만, 값 형식에 ‘?’를 붙여 사용할 수 있다. 예를 들어 `Nullable<bool>` 또는 `bool?` 형식은 내부 값인 `true`, `false` 또는 `null` 값을 저장할 수 있다. `HasValue` 속성을 사용하면 값이 저장됐는지를 Boolean 값으로 반환하고, 값이 있다면 `Value` 속성을 사용하면 실제 저장된 값을 반환한다.
|
|
|
```javascript
|
|
|
int? intValue1 = null;
|
|
|
int? intValue2 = 2;
|
|
|
|
|
|
intValue2++; // 값이 저장되어 있으므로 연산할 수 있다.
|
|
|
|
|
|
if ( intValue1 == null ) // true
|
|
|
if ( intValue2 == null ) // false
|
|
|
|
|
|
Console.WriteLine(intValue1.HasValue); // 출력 결과 : false
|
|
|
Console.WriteLine(intValue2.HasValue); // 출력 결과 : true
|
|
|
Console.WriteLine(intValue2.Value); // 출력 결과 : 3
|
|
|
Console.WriteLine(intValue2); // 출력 결과 : 3
|
|
|
```
|
|
|
|
|
|
### **구조체**
|
|
|
**구조체**는 다양한 형식의 변수와 Method를 묶어 사용자가 원하는 형식으로 정의한 것이다. **Value Type**이기 때문에 **구조체**를 선언하면 **Stack** 공간에 할당된다. 구조체 내의 변수는 매개 변수가 있는 생성자를 호출하거나, ‘.’ 연산자를 이용해 접근하여 값을 초기화한다.
|
|
|
```javascript
|
|
|
public struct Position
|
|
|
{
|
|
|
public int x,;
|
|
|
public int y;
|
|
|
|
|
|
public Position(int p1, int p2)
|
|
|
{
|
|
|
x = p1;
|
|
|
y = p2;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
#### **구조체의 특징**
|
|
|
* 구조체의 필드는 `const` 또는 `static`으로 선언한 경우에만 초기화를 할 수 있다.
|
|
|
* 매개 변수가 없는 생성자인 기본 생성자를 명시적으로 선언할 수 없다.
|
|
|
* 매개 변수가 있는 생성자는 선언할 수 있다. 단, 모든 필드에 값을 초기화해야 한다.
|
|
|
* 클래스와 달리 매개 변수가 있는 생성자를 선언하면, 기본 생성자는 묵시적으로 선언 된다.
|
|
|
* 인터페이스를 구현할 수는 있지만, 다른 구조체를 상속할 수는 없다.
|
|
|
* `new` 연산자를 사용하여 선언해도 되고, 사용하지 않고 선언해도 된다.
|
|
|
* **Nullable 형식**을 사용하여 `null` 값을 할당할 수 있다.
|
|
|
|
|
|
### **Stack vs. Heap**
|
|
|
#### **Stack**
|
|
|
*Stack*은 가장 나중에 들어간 데이터가 먼저 출력(LIFO, Last In First Out)된다는 특징을 가진 자료구조이다. **Stack**은 자료구조에서 다루는 *Stack*의 원리로 데이터를 저장하는 메모리 공간이다. Thread는 이 공간을 활용해서 Method의 실행, 지역변수 선언, 호출 후 실행될 주소를 처리한다. **Stack**은 기본적으로 1MB 공간을 할당하는데 이 공간을 넘어가면 *Stack Overflow*가 발생한다. 예를 들어 재귀(recursive)로 Method를 계속해서 호출하면 **Stack**의 공간이 모두 사용되어 *Stack Overflow*가 발생한다. 이 경우 오류를 알리는 Method를 호출할 공간조차 없기 때문에 정확한 원인을 파악하는 데 어려움이 있다.
|
|
|
|
|
|
#### **Heap**
|
|
|
**Heap**은 프로그램 실행 중 필요로 요청했을 때 저장하는 메모리 공간이다. 어느 시점에 어느 정도의 메모리 공간이 필요한지를 예상할 수 없으므로 **Heap**의 크기는 프로그램 실행 중에 결정된다. C#에서는 `new` 연산자로 참조 형식의 변수 또는 객체를 선언하면 **Heap**에 할당된다. 또한, **CLR(Common Language Runtime)**의 Garbage Collector가 실행되면서 **Heap**을 관리하기 때문에 사용되지 않는 공간은 해제하여 여유 공간을 확보한다.
|
|
|
|
|
|
### **Value Type vs. Reference Type**
|
|
|
#### **Value Type**
|
|
|
**Value Type**은 변수의 값 자체가 **Stack**에 할당되는 형식이다. 기본 자료형(string은 예외) 또는 구조체 중 배열이 아닌 하나로 선언한 변수가 **Value Type**에 속하다,
|
|
|
|
|
|
#### **Reference Type**
|
|
|
**Reference Type**은 데이터를 저장하기 위해 **Heap**에 메모리를 할당하고, **Stack**의 변수에는 **Heap**에 할당된 데이터의 주소를 가리키는 형식이다. 기본 자료형의 string, 배열, 클래스, 클래스 등이 **Reference Type**에 속한다.
|
|
|
|
|
|
#### **Value type과 Reference type 비교**
|
|
|
| **구분** | **Value type** | **Reference type** |
|
|
|
| -------- | -------- | -------- |
|
|
|
| **할당 위치** | Stack | Heap |
|
|
|
| **저장 내용** | 데이터(값) | 데이터가 위치한 메모리 주소 |
|
|
|
| **변수 종류** | 기본 자료형(string 제외), 구조체, 열거형 | string, 배열, 클래스 등 |
|
|
|
| **매개 변수** | Call by Value | Call by Reference |
|
|
|
| **소멸 시기** | 정의한 범위를 벗어날 때 | Garbage Collector에 의해 |
|
|
|
|
|
|

|
|
|
|
|
|
### **제어문 (선택문)**
|
|
|
#### **if 문**
|
|
|
**if 문**은 괄호 안에 조건식을 지정한 후에 그 결과가 `true`이면 포함된 구문을 실행하고, `false`이면 실행하지 않고 다음 코드로 넘어간다. 결과가 `false`인 경우에도 `else`를 사용해 구문을 추가할 수 있고, `else if`를 사용해 조건을 중첩할 수도 있다.
|
|
|
```javascript
|
|
|
int number = 3;
|
|
|
|
|
|
if ( number > 0 )
|
|
|
{
|
|
|
Console.WriteLine("Positive Number");
|
|
|
}
|
|
|
else if ( number < 0 )
|
|
|
{
|
|
|
Console.WriteLine("Negative Number");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Console.WriteLine("Zero");
|
|
|
}
|
|
|
|
|
|
// 출력 결과 : Positive Number
|
|
|
```
|
|
|
|
|
|
#### **조건 연산자**
|
|
|
**조건 연산자**(또는 ***삼항 연산자***)는 조건식의 결과인 `treu` 또는 `false`에 따라 표현식의 두 값 중 하나를 반환한다. *조건식*의 결과가 `true`이면 *표현식1*을 반환하고, `false`이면 *표현식2*를 반환한다.
|
|
|
```
|
|
|
(조건식) ? 표현식1 : 표현식2;
|
|
|
```
|
|
|
```javascript
|
|
|
int number = 3;
|
|
|
string result;
|
|
|
|
|
|
result = (number % 2 == 0) ? "짝수" : "홀수";
|
|
|
|
|
|
Console.WriteLine(result); // 출력 결과 : 홀수
|
|
|
```
|
|
|
|
|
|
#### **switch 문**
|
|
|
**switch 문**은 *조건식*과 같은 경우를 선택하여 해당 구문을 실행한다. `case` 안에 구문 마지막에는 `break`을 사용해야 **swtich 문**을 끝낼 수 있으며, `default` 사용하여 나머지 조건에 해당하는 구문을 실행할 수도 있다.
|
|
|
```javascript
|
|
|
int value = 1;
|
|
|
|
|
|
switch (value)
|
|
|
{
|
|
|
case 1:
|
|
|
Console.WriteLine("Case 1");
|
|
|
break;
|
|
|
case 2:
|
|
|
Console.WriteLine("Case 2");
|
|
|
break;
|
|
|
default:
|
|
|
Console.WriteLine("Default case");
|
|
|
break; // 생략 가능
|
|
|
}
|
|
|
|
|
|
// 실행 결과 : Case 1
|
|
|
```
|
|
|
|
|
|
### **제어문 (반복문)**
|
|
|
#### **for 문**
|
|
|
**for 문**은 *초기화* 코드가 실행 후 *조건식* -> *구문* -> *반복문*을 번갈아 가며 *조건식*의 결과가 `false`가 될 때까지 실행을 반복한다.
|
|
|
```
|
|
|
for ( 초기화; 조건식; 반복문 )
|
|
|
구문;
|
|
|
```
|
|
|
```javascript
|
|
|
int sum = 0;
|
|
|
|
|
|
for (int i = 1; i <= 5; i++)
|
|
|
{
|
|
|
sum += i;
|
|
|
}
|
|
|
|
|
|
Console.WriteLine(sum); // 실행 결과 : 15
|
|
|
```
|
|
|
|
|
|
#### **foreach 문**
|
|
|
**foreach 문**은 배열이나 **Collection**에 있는 데이터를 처음부터 끝까지 반복하면서 선언된 변수에 각 요소를 넣어 구문 안에서 해당 변수를 사용할 수 있게 해준다.
|
|
|
```
|
|
|
foreach ( 자료형 변수명 in 표현식 )
|
|
|
구문;
|
|
|
```
|
|
|
```javascript
|
|
|
int [] array = new int[] { 1, 2, 3, 4, 5 };
|
|
|
int sum = 0;
|
|
|
|
|
|
foreach (int element in array )
|
|
|
{
|
|
|
sum+= element;
|
|
|
}
|
|
|
|
|
|
Console.WriteLine(sum); // 실행 결과 : 15
|
|
|
```
|
|
|
|
|
|
#### **while 문**
|
|
|
**while 문**은 *조건식*의 결과가 `false`가 될 때까지 반복할 *구문*을 실행하면서 반복한다.
|
|
|
```
|
|
|
while (조건식)
|
|
|
구문;
|
|
|
```
|
|
|
```javascript
|
|
|
int i;
|
|
|
int sum = 0;
|
|
|
|
|
|
i = 1;
|
|
|
while (i <= 5)
|
|
|
{
|
|
|
sum += i;
|
|
|
i++;
|
|
|
}
|
|
|
|
|
|
Console.WriteLine(sum); // 실행 결과 : 15
|
|
|
```
|
|
|
|
|
|
#### **do-while 문**
|
|
|
**do-while 문**은 **while 문**과 마찬가지로 *조건식*의 결과가 `false`일 때까지 포함된 구문을 실행하면서 반복한다. **while 문**은 처음 실행될 때 *조건식*을 먼저 확인하지만, **do-while 문**은 *조건식*의 결과와 상관없이 반복할 구문을 최소 한번은 실행한다.
|
|
|
```
|
|
|
do
|
|
|
구문;
|
|
|
while (조건식);
|
|
|
```
|
|
|
```javascript
|
|
|
int i;
|
|
|
int sum = 0;
|
|
|
|
|
|
i = 1;
|
|
|
do
|
|
|
{
|
|
|
sum += i;
|
|
|
i++;
|
|
|
} while (i <= 5);
|
|
|
|
|
|
Console.WriteLine(sum); // 실행 결과 : 15
|
|
|
```
|
|
|
|
|
|
### **제어문 (점프문)**
|
|
|
#### **break 문**
|
|
|
**break 문**은 `switch` 또는 `for`/`foreach`/`while`/`do`와 같은 반복문 내에서만 사용될 수 있다. **switch 문** 또는 `break`를 둘러싸고 있는 반복문을 종료하는 데 사용한다.
|
|
|
```javascript
|
|
|
int sum = 0;
|
|
|
|
|
|
for (int i = 1; i <= 100; i++)
|
|
|
{
|
|
|
sum += i;
|
|
|
|
|
|
if (i == 5)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
Console.WriteLine(sum); // 실행 결과 : 15
|
|
|
```
|
|
|
|
|
|
#### **continue 문**
|
|
|
**continue 문**은 반복문 내에서 **continue 문** 이후의 구문을 생략하고 다음 조건식을 실행하는 데 사용한다.
|
|
|
```javascript
|
|
|
int sum = 0;
|
|
|
|
|
|
for (int i = 1; i <= 10; i++)
|
|
|
{
|
|
|
if (i % 2 == 0)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
sum += i;
|
|
|
}
|
|
|
|
|
|
Console.WriteLine(sum); // 실행 결과 : 25
|
|
|
```
|
|
|
|
|
|
#### **goto 문**
|
|
|
**goto 문**은 미리 선언된 *레이블 문*으로 제어의 흐름을 옮기는 데 사용한다.
|
|
|
|
|
|
#### **return 문**
|
|
|
**return 문**은 자신이 속한 Method의 실행을 종료하고 호출한 Method로 반환시킨다. 이때 반환할 값이 있으면 같이 반환된다. `void` 형식의 Method의 경우는 **return 문**을 생략할 수 있다.
|
|
|
```javascript
|
|
|
int computeArea(int width, int height)
|
|
|
{
|
|
|
int area = width * height;
|
|
|
return area;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### **연산자**
|
|
|
| **종류** | **연산자** |
|
|
|
| -------- | -------- |
|
|
|
| **관계 연산자** | >, <, >=, <=, ==, != |
|
|
|
| **논리 연산자** | &&, ||, ^, ! |
|
|
|
| **산술 연산자** | +, -, *, /, % |
|
|
|
| **대입 연산자** | =, +=, -=, *=, /=, &= |
|
|
|
| **대입 연산자** | ++, -- |
|
|
|
|
|
|
| **연산자** | **특징** | **예시** |
|
|
|
| -------- | -------- | -------- |
|
|
|
| `new` | 배열 선언 또는 객체를 선언하고 생성자를 호출 | Object obj = new Object(); |
|
|
|
| `typeof(T)` | T에 대한 형식 객체를 반환 | Type t = typeof(int); |
|
|
|
| `checked` | 산술 연산 및 변환에 대한 Overflow를 검사 | checked(2147483647 + ten) |
|
|
|
| `unchecked` | 산술 연산 및 변환에 대한 Overflow 검사를 무시 | unchecked(2147483647 + ten) |
|
|
|
| `default(T)` | T 형식의 기본값을 반환 | T temp = default(int); |
|
|
|
| `delegate` | Anonymous Method를 정의 | Del d = delegate() { } |
|
|
|
| `await` | 기다리던 작업이 완료될 때까지 비동기 Method를 일시 중단 | byte[] urlContents = await getContentsTask; |
|
|
|
| `is` | 형 변환에 대한 가능성 여부를 `true`, `false`로 반환 | if (d as Base) |
|
|
|
| `as` | 형 변환이 가능하면 변환된 값을 반환하고, 불가능하면 `null`을 반환 | Base b = d as Base; |
|
|
|
| `??` | 피연산자가 `null`이 아닐 경우 왼쪽 피연산자를 반환하고, `null`일 경우 오른쪽 피연산자를 반환 | x ?? -1 |
|
|
|
| `=>` | Lambda 식을 사용 | (a, b) => a + b | |
|
|
\ No newline at end of file |