기본 문법
기본 자료형
정수형
| 자료형 | 크기 | 기본값 | 범위 | .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.UInt32 |
| 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 | ±1.5e-45 ~ ±3.4e38 | System.Single |
| double
| 8byte | 0.0D | ±5.0e-324 ~ ±1.7e308 | System.Double |
| decimal
| 162byte | 0.0M | ±1.0×10e ~ ±7.9×10e28 | System.Decimal |
문자형
| 자료형 | 크기 | 기본값 | 범위 | 인코딩 방식 | .NET Framework 형식 |
| -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| char
| 2byte | ‘\0’ | U+0000 ~ U+FFFF | UTF-16 | System.Char |
| string
| 글자당 2byte | null
| 문자열 | UTF-16 | System.String |
논리형
| 자료형 | 크기 | 기본값 | 범위 | .NET Framework 형식 |
| -------- | -------- | -------- | -------- | -------- | -------- |
| bool
| | false | true, false | System.Boolean |
var 형식
변수의 형식을 지정해줄 필요 없이 var 형식으로 선언하면 값의 종류에 따라 컴파일러에서 가장 적합한 형식으로 결정하여 할당한다.
var i = 3; // int
var d = 3.0; // double
var s = "value"; // String
Console.WriteLine(i.GetType().FullName()); // 출력 결과 : System.Int32
Console.WriteLine(d.GetType().FullName()); // 출력 결과 : System.Double
Console.WriteLine(s.GetType().FullName()); // 출력 결과 : System.String
var 형식 사용의 제약 사항
- 클래스의 속성으로 선언할 수 없으며, 지역 변수로 선언하여 사용 할 수 있다.
- 변수 선언과 동시에 반드시 초기화되어야 하며,
null
또는 Anonymous Method로는 초기화할 수 없다. -
var 형식으로 선언된 변수를 초기화 식에서 사용할 수 없다. (ex.
var i = (i = 10));
)
Nullable 형식
Nullable 형식은 일반적인 형식의 값 이외에도 null
값을 저장할 수 있는 형식이다. Nullable<T>
와 같이 구조체 형태로 선언하지만, 값 형식에 ‘?’를 붙여 사용할 수도 있다. 예를 들어 Nullable<bool>
또는 bool?
형식은 내부 값인 true
, false
또는 null
값을 저장할 수 있다. HasValue
속성을 사용하면 값이 저장됐는지를 Boolean 값으로 반환하고, 값이 있다면 Value
속성을 사용하면 실제 저장된 값을 반환한다.
int? number1 = null;
int? number2 = 2;
Nullable<int> number3 = null; // Nullable<int>와 int?는 같은 형태
intValue2++; // 값이 저장되어 있으므로 연산할 수 있다.
if ( number1 == null ) { } // true
if ( number2 == null ) { } // false
if ( number2 == 3) { } // true
Console.WriteLine(number1.HasValue); // 출력 결과 : false
Console.WriteLine(number2.HasValue); // 출력 결과 : true
Console.WriteLine(number2.Value); // 출력 결과 : 3
Console.WriteLine(number2); // 출력 결과 : 3
구조체
구조체는 Field, Method, Event, Indexer와 같은 *멤버(Member)*들을 묶어 사용자가 원하는 형식으로 정의한 것이다. Filed는 클래스 내부에 선언된 속성으로 임의 형식의 변수를 말한다. 멤버를 선언할 때 접근 한정자(private
, protected
, public
)를 생략하면 private
으로 정의된다. 구조체는 Value Type으로 할당되기 때문에 선언할 때 Stack 공간에 데이터들이 저장된다. 구조체의 Field는 매개 변수가 있는 생성자를 호출하거나, ‘.’ 연산자를 이용해 값을 초기화할 수 있다.
public struct Position
{
public int x,;
public int y;
public Position(int p1, int p2)
{
x = p1;
y = p2;
}
}
Position position;
position.x = 2;
position.y = 3;
구조체의 특징
- 구조체의 필드는
const
또는static
으로 선언한 경우에만 초기화를 할 수 있다. - 매개 변수가 없는 생성자인 기본 생성자를 명시적으로 선언할 수 없다.
- 매개 변수가 있는 생성자는 선언할 수 있다. 단, 모든 필드에 값을 초기화해야 한다.
- 클래스와 달리 매개 변수가 있는 생성자를 선언하면, 기본 생성자는 묵시적으로 선언 된다.
- 인터페이스를 구현할 수는 있지만, 다른 구조체를 상속할 수는 없다.
-
new
연산자를 사용하여 선언해도 되고, 사용하지 않고 선언해도 된다. -
Nullable 형식을 사용하여
null
값을 할당할 수 있다.
Stack vs. Heap
Stack
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의 변수에 저장하여 데이터를 가리키는 형식이다. 기본 자료형의 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
를 사용해 조건을 중첩할 수도 있다.
int number = 3;
if ( number > 0 )
{
Console.WriteLine("Positive Number");
}
else if ( number < 0 )
{
Console.WriteLine("Negative Number");
}
else
{
Console.WriteLine("Zero");
}
// 출력 결과 : Positive Number
switch 문
switch 문은 조건식과 같은 경우를 선택하여 해당 구문을 실행한다. case
안에 구문 마지막에는 break
을 사용해야 swtich 문을 끝낼 수 있으며, default
사용하여 나머지 조건에 해당하는 구문을 실행할 수도 있다. switch
의 조건식에는 정수형 변수(int
, long
등), bool
, char
, string
, enum
또는 이러한 형식들의 Nullable 형식을 사용할 수 있다. 따라서 case
에는 이러한 형식들의 값과 null
을 사용할 수 있다.
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 ( 초기화; 조건식; 반복문 )
구문;
int sum = 0;
for (int i = 1; i <= 5; i++)
{
sum += i;
}
Console.WriteLine(sum); // 실행 결과 : 15
foreach 문
foreach 문은 배열이나 Collection에 있는 데이터를 처음부터 끝까지 반복하면서 선언된 변수에 각 요소를 넣어 구문 안에서 해당 변수를 사용할 수 있게 해준다.
foreach ( 자료형 변수명 in 표현식 )
구문;
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 (조건식)
구문;
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 (조건식);
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
를 둘러싸고 있는 반복문을 종료하는 데 사용한다.
int sum = 0;
for (int i = 1; i <= 100; i++)
{
sum += i;
if (i == 5)
{
break;
}
}
Console.WriteLine(sum); // 실행 결과 : 15
continue 문
continue 문은 반복문 내에서 continue 문 이후의 구문을 생략하고 다음 조건식을 실행하는 데 사용한다.
int sum = 0;
for (int i = 1; i <= 10; i++)
{
if (i % 2 == 0)
{
continue;
}
sum += i;
}
Console.WriteLine(sum); // 실행 결과 : 25
goto 문
goto 문은 레이블로 지정한 위치로 이동할 때 사용한다. goto 문을 사용하기 위해 원하는 위치에 레이블을 미리 지정해야 한다,
return 문
return 문은 자신이 속한 Method의 실행을 종료하고 호출한 Method로 반환시킨다. 이때 반환할 값이 있으면 같이 반환된다. void
형식의 Method의 경우는 return 문을 생략할 수 있다.
int computeArea(int width, int height)
{
int area = width * height;
return area;
}
연산자
>
, <
, >=
, <=
, ==
, !=
관계 연산자 :
&&
, ||
, ^
, !
, |
논리 연산자 :
+
, -
, *
, /
, %
산술 연산자 :
=
, +=
, -=
, *=
, /=
, &=
대입 연산자 :
++
, --
증감 연산자 : 기타 연산자
-
:? : 조건 연산자(또는 삼항 연산자)라고도 하며 조건식의 결과인
true
또는false
에 따라 표현식의 두 값 중 하나를 반환하는 연산자이다. 조건식의 결과가true
이면 표현식1을 반환하고,false
이면 표현식2를 반환한다.
(조건식) ? 표현식1 : 표현식2;
int number = 3;
string result;
result = (number % 2 == 0) ? "짝수" : "홀수";
Console.WriteLine(result); // 출력 결과 : 홀수
-
?? : 피연산자가
null
이 아닐 경우 왼쪽 피연산자를 반환하고,null
일 경우 오른쪽 피연산자를 반환한다.
int? number1 = null;
int? number2 = 3;
int result1 = number1 ?? -1;
int result2 = number2 ?? -1;
System.Console.WriteLine(result1); // 출력 결과 : -1
System.Console.WriteLine(result2); // 출력 결과 : 3
- new : 배열 선언하거나, 객체를 선언하고 생성자를 호출한다.
int array = new int[5];
Object obj = new Object();
- default(T) : T 형식의 기본값을 반환한다.
int defaultInt = default(int);
double defaultDouble = default(double);
Object defaultObjet = default(Object);
Console.WriteLine(defaultInt); // 실행 결과 : 0
Console.WriteLine(defaultDouble); // 실행 결과 : 0.0
Console.WriteLine(defaultObjet); // 실행 결과 : null
- typeof(T) : T 형식의 대한 객체를 반환한다.
Type typeInt = typeof(int);
Type typeObject = typeof(Object);
Console.WriteLine(typeInt); // 실행 결과 : System.Int32
Console.WriteLine(typeObject); // 실행 결과 : System.Object
- checked : 정수 계열 형식의 산술 연산 및 변환에 대한 Overflow를 검사한다.
int number = 10;
int result;
try
{
result = checked(2147483647 + number); // OverflowException
}
catch (System.OverflowException e)
{
Console.WriteLine(e.ToString());
}
// 실행 결과 : System.OverflowException: 산술 연산으로 인해 오버플로가 발생했습니다. (이후 생략)
- unchecked : 정수 계열 형식의 산술 연산 및 변환에 대한 Overflow 검사를 무시한다.
int number = 10;
int result;
result = unchecked(2147483647 + number);
Console.WriteLine(result); // 실행 결과 : -2147483639
-
is : 형 변환에 대한 가능성 여부를
true
,false
로 반환해 준다.
class BaseClass { }
class DerivedClass : BaseClass { }
BaseClass b = new BaseClass();
BaseClass d = new DerivedClass();
if (b is BaseClass) { } // true
if (b is DerivedClass) { } // false
if (d is BaseClass) { } // true
if (d is DerivedClass) { } // true
-
as : 형 변환이 가능하면 변환된 값을 반환하고, 불가능하면
null
을 반환해 준다.
class BaseClass { }
class DerivedClass : BaseClass { }
BaseClass b = new BaseClass();
DerivedClass d = new DerivedClass();
BaseClass b2 = d as BaseClass;
DerivedClass d2 = b as DerivedClass;
if(b2 != null) { } // true
if(d2 != null) { } // false