Tag Archives: C#

뇌를 자극하는 C# 4.0 프로그래밍/ 코드의 흐름 제어하기

컴퓨터가 이해할 수 있는 코드는 바보라도 짤 수 있다.
좋은 프로그래머는 사람이 이해할 수 있는 코드를 짠다.
— 마틴 파울러

분기문

  • C#에서 제공하는 분기문의 종류
    • if – if/ else if/ else
    • switch

반복문

  • C#에서 제공하는 반복문의 종류
    • while
    • do while
    • for
    • foreach

점프문

  • C#에서 제공하는 점프문의 종류
    • break
    • continue
    • goto
    • return
    • throw

뇌를 자극하는 C# 4.0 프로그래밍/ 데이터를 가공하는 연산자

C#에서 제공하는 연산자 둘러보기

분류 연산자
산술 연산자 +, -, *, , %
증가/ 감소 연산자 ++, —
관계 연산자 <, >, ==, !=, <=, >=
조건 연산자 ?:
논리 연산자 &&,
비트 연산자 <<, >>, &, ^, ~
할당 연산자 =, +=, -=, *=, /=, %=,

산술 연산자

연산자 설명 지원 형식
+ 양쪽 피연산자를 더합니다 모든 수치 데이터 형식을 지원합니다.
왼쪽 피연산자에서 오른쪽 피연산자를 차감합니다 모든 수치 데이터 형식을 지원합니다.
* 양쪽 피연산자를 곱합니다 모든 수치 데이터 형식을 지원합니다.
/ 왼쪽 연산자를 오른쪽 피연산자로 나눈 몫을 구합니다 모든 수치 데이터 형식을 지원합니다.
% 왼쪽 연산자를 오른쪽 피연산자로 나눈 후의 나머지를 구합니다 모든 수치 데이터 형식을 지원합니다.

증가 연산자와 감소 연산자

연산자 이름 설명 지원 형식
++ 증가 연산자 피연산자의 값을 1 증가시킵니다 모든 수치 데이터 형식을 지원합니다.
감소 연산자 피연산자의 값을 1 감소시킵니다 모든 수치 데이터 형식을 지원합니다.

문자열 결합 연산자

// 아래와 같이 하면 result에는 123456이 저장된다.
string result = "123" + "456";

관계 연산자

연산자 설명 지원 형식
< 왼쪽 피연산자가 오른쪽 피연산자보다 작으면 참, 아니면 거짓 모든 수치 데이터 형식을 지원합니다.
> 왼쪽 피연산자가 오른쪽 피연산자보다 크면 참, 아니면 거짓 모든 수치 데이터 형식을 지원합니다.
<= 왼쪽 피연산자가 오른쪽 피연산자보다 작거나 같으면 참, 아니면 거짓 모든 수치 데이터 형식을 지원합니다.
>= 왼쪽 피연산자가 오른쪽 피연산자보다 크거나 같으면 참, 아니면 거짓 모든 수치 데이터 형식을 지원합니다.
== 왼쪽 피연산자가 오른쪽 피연산자와 같으면 참, 아니면 거짓 모든 수치 데이터 형식을 지원합니다.
!= 왼쪽 피연산자가 오른쪽 피연산자와 다르면 참, 아니면 거짓 모든 수치 데이터 형식을 지원합니다.

논리 연산자

A B A && B
거짓 거짓
거짓 거짓
거짓 거짓 거짓
A B A || B
거짓
거짓
거짓 거짓 거짓
A !A
거짓
거짓

조건 연산자

// 조건식 ? 조건식이 참일 때의 값 : 조건식이 거짓일 때의 값
// 아래와 같이 하면 result에는 "삼십"이 저장된다.
int a = 30;
string result = a == 30 ? "삼십" : "삼십아님";

// 추가 - 본문엔 없는 연산자. ??
// null 타입에 한정하여 ?과 같은 조건 연산자가 ?? 이다
// 아래 코드에서 result가 null이 아니면 왼쪽의 "널 아님" 이 대입되고, result가 null이면 오른쪽의 "널"이 대입된다.
string result = "널 아님" ?? "널";

비트 연산자

연산자 이름 설명 지원 형식
<< 왼쪽 시프트 연산자 첫 번째 피연산자의 비트를 두 번째 피연산자의 수만큼 왼쪽으로 이동 시킵니다. 첫 번째 피연산자는 int, uint, long, ulong 이며 두 번째 피연산자는 int 형식만 지원됩니다.
>> 오른쪽 시프트 연산자 첫 번째 피연산자의 비트를 두 번째 피연산자의 수만큼 오른쪽으로 이동 시킵니다. 첫 번째 피연산자는 int, uint, long, ulong 이며 두 번째 피연산자는 int 형식만 지원됩니다.
& 논리곱(AND) 연산자 두 피연산자의 비트 논리곱을 수행합니다. 정수 계열 형식과 bool 형식에 대해 사용할 수 있습니다.
| 논리합(OR) 연산자 두 피연산자의 비트 논리합을 수행합니다. 정수 계열 형식과 bool 형식에 대해 사용할 수 있습니다.
^ 배타적 논리합(XOR) 연산자 두 피연산자의 비트 배타적 논리합을 수행합니다. 정수 계열 형식과 bool 형식에 대해 사용할 수 있습니다.
~ 보수(NOT) 연산자 피연산자의 비트를 0은 1로, 1은 0으로 반전시킵니다. 단항 연산자입니다. int, uint, long, ulong에 대해 사용이 가능합니다.

시프트 연산자

비트를 왼쪽이나 오른쪽으로 이동시키는 것.

  • 비트를 왼쪽으로 이동 시키는 경우

  • 비트를 오른쪽으로 이동 시키는 경우

  • 음수의 시프트 연산
    • 음수는 비트를 이동시킨 후 생긴 빈자리에 0이 아닌 1을 채워 넣는다는 점에서 차이가 있다.

  • 시프트 연산 사용 방법

  • 시프트 연산의 원본 데이터를 a, 옮긴 비트 수를 b라고 할 때, 왼쪽 시프트 연산을 하면 a x 2b의 결과가, 오른쪽 시프트 연산을 하면 a ÷ 2b의 결과가 나온다.
  • 이 점을 이용해서 시프트 연산은 고속의 곱셈과 나눗셈을 구현하는데 사용되기도 하고 & 연산자와 | 연산자와 함께 byte처럼 작은 단위로 쪼개진 데이터를 다시 하나의 int나 long 형식으로 재조립하는데 사용되기도 한다.

비트 논리 연산자

  • 논리곱(&) 연산

  • 논리합(|) 연산

  • 배타적 논리합(^) 연산

  • 보수(NOT) 연산자

할당 연산자

연산자 이름 설명
= 할당 연산자 오른쪽 피연산자를 왼쪽 피연산자에게 할당합니다.
+= 덧셈 할당 연산자 a += b; 는 a = a + b;와 같습니다.
-= 뺄셈 할당 연산자 a -= b; 는 a = a – b;와 같습니다.
*= 곱셈 할당 연산자 a *= b; 는 a = a * b;와 같습니다.
/= 나눗셈 할당 연산자 a /= b; 는 a = a / b;와 같습니다.
%= 나머지 할당 연산자 a %= b; 는 a = a % b;와 같습니다.
&= 논리곱 할당 연산자 a &= b; 는 a = a & b;와 같습니다.
|= 논리합 할당 연산자 a |= b; 는 a = a | b;와 같습니다.
^= 배타적 논리합 할당 연산자 a ^= b; 는 a = a ^ b;와 같습니다.
<<= 왼쪽 시프트 할당 연산자 a <<= b; 는 a = a << b;와 같습니다.
>>= 오른쪽 시프트 할당 연산자 a >>= b; 는 a = a >> b;와 같습니다.

연산자의 우선순위

우선 순위 종류 연산자
1 증가/ 감소 연산자 후위 ++, — 연산자
2 증가/ 감소 연산자 전위 ++, — 연산자
3 산술 연산자 *, /, %
4 산술 연산자 +, –
5 시프트 연산자 <<, >>
6 관계 연산자 <, >, <=, >=, is, as
7 관계 연산자 ==. !=
8 비트 논리 연산자 &
9 비트 논리 연산자 ^
10 비트 논리 연산자 |
11 논리 연산자 &&
12 논리 연산자 ||
13 조건 연산자 ?:
14 할당 연산자 =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=

뇌를 자극하는 C# 4.0 프로그래밍/ 데이터 보관하기

데이터에도 종류가 있다

  • 데이터 형식은 ‘기본 데이터 형식 : 복합 데이터 형식’이나 ‘값 형식 : 참조 형식’으로 구분할 수 있다.

변수(Variable)

  • 아래와 같이 변수를 선언하면 컴파일러는 선언된 int 형식을 위해 메모리 공간을 할당하고 이 공간을 x라는 식별자가 사용할 수 있도록 준비해 둔다.

  • 선언된 변수에는 대입 연산자를 통해 데이터를 입력할 수 있는데 이 코드가 실행되면 x를 위해 할당된 메모리 공간에 데이터 100이 기록된다.

값 형식(Value Types)과 참조 형식(Reference Types)

  • 값 형식은 변수가 값을 담고, 참조 형식은 변수가 값이 있는 곳의 위치(참조)를 담는다.
  • 메모리 영역은 스택(Stack)과 힙(Heap)으로 구분할 수 있는데, 스택은 값 형식과 관련 있고, 힙은 참조 형식과 관련이 있다.

스택과 값 형식

  • 스택은 먼저 들어간 데이터가 아래에 쌓이고 나중에 들어간 데이터가 위에 쌓이는 형식. 먼저 들어간 데이터를 꺼내려면 그 위에 쌓인 데이터들을 모두 걷어내야 한다.

  • 값 형식의 변수들은 모두 스택에 저장된다.
  • 코드 블록 안에 생성된 모든 값형 변수들은 코드 블록이 끝나면 —} 를 만나면– 메모리에서 제거된다.

힙과 참조 형식

  • 스택은 자신이 담고 있던 데이터를 모두 제거하지만, 힙은 저장되어 있는 데이터를 스스로 제거하는 메커니즘이 없다. 힙의 데이터를 제거하는 역할은 CLR의 가비지 컬렉터가 담당 한다.
    • 가비지 컬렉터는 프로그램 뒤에 숨어 동작하면서 힙에 더는 사용하지 않는 객체가 있으면 그 객체를 쓰레기로 간주하고 수거하는 기능을 한다.
    • 힙이라는 메모리 영역이 필요한 이유는 코드 블록이 끝난 후에도 데이터를 유지하고 싶기 때문. 스택은 코드 블록이 끝나면 데이터가 사라지기 때문에 한계가 있다.
  • 참조 형식의 변수는 힙과 스택을 모두 사용한다. 힙 영역에는 데이터를 저장하고, 스택 영역에는 데이터가 저장되어 있는 힙 메모리의 주소를 저장한다.
    • 힙의 데이터를 참조 하고 있는 스택이 없으면 가비지 컬렉터가 수거해 간다.
    • 여기서 중요한 점은 가비지 컬렉터가 힙의 쓰레기를 언제 수거해 갈지 알 수 없다는 것. 이 부분은 최적화 이슈와도 연결된다.

기본 데이터 형식(Primitive Types)

  • C#이 제공하는 기본 데이터 형식은 모두 15가지가 존재하는데, 이들은 크게 숫자 형식, 논리 형식, 문자열 형식, 오브젝트 형식으로 구분된다.
    • 이 중 문자열 형식과 오브젝트 형식만 참조 형식이며 나머지는 모두 값 형식이다.

숫자 데이터 형식(Numeric Types)

  • 프로그래밍을 구성하는 가장 많은 데이터 형식이 숫자. 이유는 다른 복잡한 데이터가 숫자를 기반으로 구성되기 때문.
    • 텍스트 데이터도 알고 보면 각 문자 하나 하나가 내부적으로 숫자 코드로 구성되어 있다. ex) a는 63, b는 64

정수 계열 형식(Integral Types)

데이터 형식 설명 크기(Byte) 담을 수 있는 값의 범위
byte 부호 없는 정수 1 (8 bit) 0 ~ 255
sbyte signed byte 정수 1 (8 bit) -128 ~ 127
short 정수 2 (16 bit) -32,768 ~ 32,767
ushort unsigned short 정수 2 (16 bit) 0 ~ 65535
int 정수 4 (32 bit) -2,147,483,648 ~ 2,147,483,647
uint unsigned int 정수 4 (32 bit) 0 ~ 4,294,967,295
long 정수 8 (64 bit) -922,337,203,685,477,508 ~ -922,337,203,685,477,507
ulong unsigned long 정수 8 (64 bit) 0 ~ 18,446,744,073,709,551,615
char 유니코드 문자 2 (16 bit)

부호 있는 정수와 부호 없는 정수

  • 부호가 있는 데이터 형식은 가장 앞에 있는 비트를 부호로 사용한다.
    • 아래의 이미지는 -127일 것 같지만 사실은 -1 값이 된다. 이유는 그 아래의 설명 참조.

  • 직관적으로 생각하기엔 음수는 맨 앞의 비트를 1로 표현하고 나머지는 본래 숫자 자체로 표현할 것 같은데 –이런 방법을 부호와 절대값 방식 (Sign-and-magnitude)이라고 한다– 이 방식을 사용하면 0이 +0(0000 0000)과 -0(1000 0000)으로 표현되는 문제가 발생한다.
  • 이러한 문제를 해결하기 위해 음수 표현은 2의 보수법 (2’s Complement)이라는 방식을 사용하는데 그 표현 방법은 다음과 같다.
    1. 먼저 수 부분 비트를 채운다.
    2. 전체 비트를 반전 시킨다.
    3. 반전된 비트에 1을 더한다.
  • 아래의 이미지는 -1을 2의 보수법으로 표현한 예

데이터가 넘쳐 흘러요

  • 데이터 형식의 크기를 넘어서는 값을 담게 될 때 나타나는 현상을 오버플로우 (Overflow)라고 한다.
    • byte의 최대값은 1111 1111(255)인데 여기에 1을 더하면 1 0000 0000이 된다. byte는 8개의 비트만 담을 수 있기 때문에 왼쪽의 비트는 버리고 오른쪽의 8개의 비트만 보관하기 때문에 byte 형식의 변수가 오버플로우가 되면 0이 된다.
  • 이와 반대로 값 형식의 최저값보다 작은 데이터를 저장하면 언더플로우 (Underflow)가 일어난다.

부동 소수점 형식(Floating Point Types)

  • 부동 소수점이란 소수점이 고정되어 있지 않고 움직이면서 수를 표현한다는 뜻이다.
    • 이 때문에 부동 소수점 방식은 정밀도에 한계가 있음.
데이터 형식 설명 크기(Byte) 담을 수 있는 값의 범위
float 단일 정밀도 부동 소수점 형식 (7개의 자릿수만 다룰 수 있음) 4 (32 bit) -3.402823e38 ~ 3.402823e38
double 복수 정밀도 부동 소수점 형식 (15-16개의 자릿수를 다룰 수 있음) 8 (64 bit) -1.79769313486232e308 ~ 1.79769313486232e308
  • 부동 소수점 형식은 실수 영역의 데이터를 다룰 수 있지만 다음과 같은 이유로 정수 형식을 대체할 수 없다.
    1. 소수점을 표현하기 위해 일부 비트를 사용하기 때문에 같은 크기의 정수 계열 형식과 같은 크기의 수를 표현할 수 없다.
    2. 산술 연산 과정이 정수 계열 형식보다 복잡해서 느리다.

  • float 형식의 경우 맨 앞의 1비트를 부호 전용으로 사용하고, 그 다음 8비트를 소수점의 위치를 나타내는 지수부로 사용하고, 나머지 23비트를 수를 표현하는 가수부로 사용한다.
  • float는 -3.402823e38(-3.402823 x 1038) ~ 3.402823e38(3.402823 x 1038)에 이르는 어마어마한 크기를 다룰 수 있지만 유효숫자는 7자리 밖에 되지 않는다. 7자리를 넘어가는 수는 ‘대략적으로’ 표현한다는 뜻.

Decimal 형식

데이터 형식 설명 크기(Byte) 담을 수 있는 값의 범위
decimal 29자리 데이터를 표현할 수 있는 소수 형식 16 (128 bit) ±1.0 x 10e-28 ~ ±7.9 x 10e28
  • decimal도 범위의 한계는 있지만, float이나 double보다 높은 정밀도를 나타내기 때문에 큰 수를 다뤄야 하는 경우에 유용하다.

문자 형식과 문자열 형식

  • char 형식은 정수를 다루는 데이터 형식이지만 문자 데이터를 다룬다.
    • 작은 따옴표 '를 사용한다.
  • string은 여러 char가 묶여 있는 데이터 형식. string 형식은 참조형이기 때문에 정해진 크기나 담을 수 있는 데이터의 범위가 따로 정해져 있지 않다.
    • 큰 따옴표 "를 사용한다.

논리 형식

데이터 형식 설명 크기(Byte) 담을 수 있는 값의 범위
bool 논리 형식 1 (8 bit) true, false
  • C 언어에서는 논리 형식이 없었기 때문에 0을 거짓 0이 아니면 참으로 사용했었다.

object 형식

  • C#에서는 object가 모든 데이터를 다룰 수 있도록 모든 데이터 형식이 object 형식을 상속 받도록 정의해 놨다.

박싱(boxing)과 언박싱(unboxing)

  • object 형식은 값 형식의 데이터를 힙에 할당하기 위한 ‘박싱(boxing)’ 기능을 제공한다. object 형식에 값 형식의 데이터를 할당하려는 시도가 이루어지면 object 형식은 박싱을 수행해서 해당 데이터를 힙에 할당한다.

  • 이와 반대로 힙에 있던 값 형식 데이터를 값 형식 객체에 다시 할당해야 하는 경우가 있는데 이를 ‘언박싱(unboxing)’이라고 한다.

데이터 형식 바꾸기

크기가 서로 다른 정수 형식 사이의 변환

  • 작은 정수 형식의 변수에 있는 데이터를 큰 정수 형식의 변수로 옮길 때는 문제가 없지만 그 반대의 경우 오버플로우가 발생할 수 있다. 물론 큰 변수로부터 옮겨오는 데이터가 작은 형식의 변수가 담을 수 있는 크기라면 문제 없다.

크기가 서로 다른 부동 소수점 형식 사이의 변환

  • 부동 소수점 형식의 특성상 float과 double의 사이의 변환에 오버플로우는 존재하지 않는다. 다만 정밀도에 손상이 생길 수는 있다.

부동 소수점 형식과 정수 형식 사이의 변환

  • 부동 소수점 형식의 변수를 정수 형식으로 변환하면 데이터에서 소수점 아래는 버리고 소수점 위의 값만 남긴다. 0.1이나 0.9나 모두 정수 형식으로 변환하면 0이 된다.

문자열을 숫자로, 숫자를 문자열로

int a = int.Parse("12345");
float b = float.Parse("123.45");
string c = a.ToString();
  • 문자열을 숫자로, 숫자열을 문자로 변환하려고 하면 컴파일도 되지 않는다. 그러나 이 형식 변환은 매우 자주 있는 일이기 때문에 C#에서는 이 둘 사이의 변환에 위와 같은 별도의 방법을 마련해 주고 있다.
    • 문자열을 int나 float 형식으로 바꿀 때는 Parse() 메소드를 사용하고, 숫자 형식을 문자열로 바꿀 때는 ToString() 메소드를 사용한다.

상수(Constants)와 열거 형식(Enumerator)

상수 – 전 언제나 변하지 않을 거에요

const int a = 3;
const double b = 3.14;
const string c = "abcde";
  • 상수는 const 키워드를 데이터 타입 앞에 붙이면 된다.
    • 상수는 실행 중에 바꿀 수 없기 때문에 선언 시에 값을 넣어줘야 한다.

열거 형식 – 여러 개의 상수를 정리 합시다

// 열거형 선언
enum Dialog { Yes, No, Cancel, Confirm, OK }

// 열거형 변수 사용
Dialog result = Dialog.Yes;
  • 실제 프로그래밍시에 대단히 유용한 자료형. 상수이고 범위가 제한적이기 때문에 대단히 안전하고, 사용할 때 위와 같이 문자 형태로 표현되기 때문에 직관성도 높다.
  • 또한 각 열거형 상수가 값을 갖고 있기 때문에 숫자형 데이터로 변환하거나 숫자형 데이터를 열거형으로 바꾸는데도 문제가 없다.
    • 따로 값을 대입할 수도 있지만 아무런 값도 넣지 않으면 컴파일러가 0부터 1씩 증가하여 알아서 값을 넣어준다.

Nullable 형식

int? a = null;
float? b = null;
doublie? c = null;
  • 기본적으로 값 형식의 변수는 null 값을 가질 수 없는데, 만일 값 형식의 변수가 null 값을 갖도록 하려면 위와 같이 형식 이름 뒤에 ?를 붙이면 된다.
    • 이렇게 선언하면 컴파일러는 해당 변수에게 할당된 메모리 공간을 비워둔다.

var: 데이터 형식을 알아서 파악하는 똑똑한 C# 컴파일러

var a = 3; // a는 int 형식
var b = "Hello"; // b는 string 형식
  • 기본적으로 C#은 형식 검사를 강력하게 하는 언어이기 때문에 선언할 때 형식을 지정해 줘야 하지만 var 라는 키워드를 통해 어떠한 타입의 형식도 받을 수 있는 변수를 선언할 수 있다.
  • 다만 var 타입의 변수는 선언할 때 반드시 값을 받아야 한다. 이는 컴파일 단계에서 컴파일러가 어떤 타입의 변수인지 알아야 하기 때문.
  • 개인적인 성향상 var 키워드의 가독성이 떨어지고 엄격함이 떨어져서 선호하지 않는데, enumerator 형식의 복잡하게 중첩된 자료형의 경우 —List<Dictionary<int, string>>와 같은– var를 쓰면 타이핑을 줄일 수 있어서 편하긴 하다.

공용 형식 시스템(Common Type System)

System.Int32 a = 123;
System.String c = "abc";
  • 공용 형식 시스템이란 .NET 프레임워크를 지원하는 모든 언어들이 따르는 데이터 형식 표준. .NET 언어들끼리의 호환성을 높이기 위해 도입되었다.
  • 만일 위와 같이 변수를 선언하면 .NET 언어 어디서든 그대로 사용될 수 있다.
Class Name C# 형식 C++ 형식 비주얼 베이직 형식
System.Byte byte unsigned char Byte
System.SByte sbyte char SByte
System.Int16 short short Short
System.Int32 int int 또는 long Integer
System.Int64 long _int64 Long
System.UInt16 ushort unsigned short UShort
System.UInt32 uint unsigned int 또는 unsigned long UInteger
System.UInt64 ulong unsigned _int64 ULong
System.Single float float Single
System.Double double double Double
System.Boolean bool bool Boolean
System.Char char wchar_t Char
System.Decimal decimal Decimal Decimal
System.IntPtr 없음 없음 없음
System.UIntPtr 없음 없음 없음
System.Object object Object* Object
System.String string String* String

뇌를 자극하는 C# 4.0 프로그래밍/ 처음 만드는 C# 프로그램

CLR에 대하여

  • C#은 CLR (Common Language Runtime) 위에서 실행된다.
    • CLR은 자바 가상 머신과 비슷한 역할을 한다.
    • CLR은 .NET 프레임워크와 함께 OS 위에 설치된다.
      • (추가) 정확히는 .NET 프레임워크가 CLR을 포함하는 관계이다.
      • CLR + managed libraries and tools = Microsoft .NET Framework
  • 네이티브 코드로 작성되어 있는 프로그램들은 –ex) Mac의 Objective-C 등– 운영체제가 직접 실행할 수 있지만, C# 컴파일러가 만들어낸 실행 파일은 운영체제가 이해할 수 없는 코드로 구성되어 있기 때문에 실행할 수 없기 때문에 다음과 같은 방식으로 컴파일이 이루어진다.
  • C# 코드의 실행 순서. 아래와 같은 방식을 JIT(Just In Time) 컴파일이라고 부른다.
    1. C# 컴파일러는 C#의 소스코드를 IL (Intermediate Language)이라는 중간 언어로 작성된 실행 파일을 만들어 낸다.
    2. 사용자가 이 파일을 실행시키면 CLR이 이 중간 코드를 읽어서 OS가 이해할 수 있는 네이티브 코드로 컴파일 한다.
  • 실행 코드를 2번에 걸쳐 번역하는 이와 같은 복잡한 과정을 사용하는 까닭은 CLR이 C# 뿐만 아니라 다른 언어도 지원하도록 설계되었기 때문.
    • 여러 언어들이 만나기 위한 지점이 IL이라는 중간 언어이고 CLR이 이 중간 언어로 쓰여진 코드를 다시 자신이 설치되어 있는 플랫폼에 최적화 시켜 컴파일 한다는 것.
  • CLR은 단순히 C#이나 기타 언어들을 동작시키는 환경 기능 외에도 프로그램의 오류를 처리하는 기능, 언어 간의 상속 지원, COM과의 상호 운영성 지원, 자동 메모리 관리(가비지 컬렉션) 등의 기능을 제공한다.

뇌를 자극하는 C# 4.0 프로그래밍

C#의 기초부터 시작해서 고급 기능까지를 두루 살피는 책. 단순히 언어의 문법과 사용법만이 이야기하는 것이 아니라 그 개념과 사용 이유에 대해서도 잘 설명하고 있어서 이해가 더욱 잘 된다.

개인적으로는 기초 없이 MSDN만 찾아보고 잘 이해 안 되던 개념들을 책을 통해 잘 이해할 수 있었던 점도 좋았고, 생각 없이 노가다로 구현한 것들에 대한 우아한 해법도 배울 수 있어서 좋았다. –람다 식이나 LINQ 등을 보면서 C#이 꽤나 근사한 언어라는 것을 깨닫게 됨– 부실했던 기초가 조금은 보강이 된 느낌.

후반부의 고급 기능들은 아직 경험해 본 바가 없어서 한 번에 잘 이해는 하지 못했는데, 꽤나 잘 정리된 것 같아서 앞으로 경험을 쌓으며 다시 훑으면 잘 이해할 수 있으리라 생각.