제어문이라 함은 말 그대로 프로그램의 흐름을 제어하는 프로그래밍 구문을 의미합니다.
1. 분기문
주어진 조건에 따라 프로그램의 흐름을 분기하여 처리합니다.
● if
주어진 조건이 참인 경우 이하 구문을 실행합니다.
static void Main(string[] args)
{
bool b = true;
if (b == true)
WriteLine("b는 참"); //b가 true이므로 해당 문장 실행
}
제어문은 기본적으로 구문 이후에 나오는 단 하나의 문장(; 기준)만을 평가 대상으로 합니다. 실행해야 할 구문이 여러 줄이라면 { 와 } 로 실행할 문자를 묶어줄 수 있습니다.
static void Main(string[] args)
{
bool b = true;
if (b == true) {
//{ 부터 } 까지의 모든 문장 실행
WriteLine("b는 참");
b = false;
}
}
참인 경우 이외에 거짓인 경우의 처리가 필요하다면 else절로 분기합니다.
static void Main(string[] args)
{
bool b = true;
if (b == true) {
WriteLine("b는 참");
b = false;
}
else {
//b가 true가 아닌 경우 실행
WriteLine("b는 거짓");
b = true;
}
}
제어가 필요한 조건을 추가하고자 한다면 else if 절을 사용합니다.
static void Main(string[] args)
{
bool b = true;
if (b == true) {
WriteLine("b는 참");
b = false;
}
else if (b == false) {
//b가 true가 아닌 경우 실행
WriteLine("b는 거짓");
b = true;
}
}
물론 위와 같은 경우에도 else절을 통해 조건에 해당되지 않는 모든 경우를 처리할 수 있습니다.
static void Main(string[] args)
{
bool? b = null;
if (b == true) {
WriteLine("b는 참");
b = false;
}
else if (b == false) {
//b가 true가 아닌 경우 실행
WriteLine("b는 거짓");
b = true;
}
else {
WriteLine("b는 true도 false도 아님");
}
}
● switch
switch는 다양한 조건에 적용할 수 있는 분기문입니다.
static void Main(string[] args)
{
int i = 10;
switch(i)
{
case 10:
WriteLine("i 값은 10");
break;
case 20:
WriteLine("i 값은 20");
break;
default:
WriteLine($"i값은 {i}");
break;
}
}
예제에서 switch는 괄호안의 i변숫값을 평가하며 해당 변수의 값에 따라 각각의 case문으로 실행을 분기하도록 하였습니다. 괄호에 올 수 있는 조건은 정수와 문자열 형식만 가능하며 만약 case문과 일치하지 않는 조건이라면 default문으로 실행을 분기할 것입니다.
각 case문에는 조건에 맞는 값을 지정하며 하위에 실행할 구문을 가지는 구조입니다. 또한 하위에 모든 구문을 실행하게 되면 마지막으로 break문을 만나게 되는데 break는 현재 실행 중인 switch문 밖으로 실행 지점을 빠져나오도록 합니다. break는 조건에 맞는 부분의 구문만 실행하도록 하는 역할을 하며 생략할 수 없습니다.
다만 break대신 goto나 return이 올 수도 있는데 goto는 실행시점을 아예 다른 곳으로 분기하도록 하는 것으로 프로그램의 유지보수를 곤란하게 한다는 문제 때문에 잘 사용하지 않는 편입니다. 대신 return의 경우에는 종종 사용되기도 하는데 break가 switch문을 빠져나오게 하고 그 이후의 실행을 계속 진행하는 거라면 return은 아예 실행을 중단시킨다는 차이가 있습니다.
C# 7.0부터는 괄호안에 오는 변수의 값이 아닌 값의 데이터 형식을 판단하는 조건이 추가되었습니다.
static void Main(string[] args)
{
object o = 10;
switch(o)
{
case int i:
WriteLine($"int 값 : {i}");
break;
case string s:
WriteLine($"string 값 : {s}");
break;
default:
WriteLine($"그외...");
break;
}
}
따라서 예제에서 처럼 object o에 들어간 값이 10이므로 int형과 일치하게 되고 해당 값은 case에 있는 int형 변수 i에 들어가게 됩니다.
case문에 있는 변수에 값이 들어간다는 점때문에 특정한 값을 다음과 같이 조건으로 추가할 수도 있습니다.
static void Main(string[] args)
{
object o = 10;
switch(o)
{
case int i when i == 10:
WriteLine("int 값 : 10");
break;
case int i when i == 20:
WriteLine("int 값 : 20");
break;
case int i:
WriteLine($"int 값은 {i}");
break;
case string s:
WriteLine($"string 값 : {s}");
break;
default:
WriteLine($"그외...");
break;
}
}
값은 when으로 지정할 수 있으며 <=나 >=처럼 다양한 관계 연산자를 활용할 수 있습니다.
참고로 예제에서 각각의 case문에서는 break;로 종료되고 있는데 필요하다면 goto문을 통해 해당 label로의 이동을 수행할 수 있고 goto case를 사용해 다른 case문으로 실행을 옮겨줄 수도 있습니다.
switch는 조건에 따라 실행을 분기하는 역활을 수행하는 게 기본이지만 필요하다면 특정 결괏값을 반환하도록 하는 식으로서의 활용도 가능합니다.
static void Main(string[] args)
{
int document = 1;
string state = document switch {
1 => "승인",
2 => "대기",
3 => "반려",
_ => "알 수 없음"
};
WriteLine(state);
}
위의 소스는 문서(document)의 상태값을 확인하여 그 값에 따라 정확한 상태를 문자열로 알려주는 가상의 예제입니다. 예제에서 document변수의 값은 1이므로 state에는 "승인"이라는 문자열 값이 들어가게 될 것입니다. 또한 switch문에서 default는 switch 식에서 언더바(_)로 대체될 수 있습니다.
뿐만 아니라 switch식에서도 when 절을 사용하여 추가적인 조건을 설정할 수도 있습니다.
static void Main(string[] args)
{
int document = 1;
bool pass = false;
string state = document switch {
1 when pass == false => "승인대기",
1 => "승인",
2 => "대기",
3 => "반려",
_ => "알 수 없음"
};
WriteLine(state);
}
2. 반복문
흔히 '루프'라고도 하며 특정 작업의 반복을 위해 사용됩니다.
● while
조건이 true인 경우 주어진 구문을 실행합니다.
static void Main(string[] args)
{
int download = 0;
while(download < 100) {
++download;
}
WriteLine($"완료 {download}");
}
● do while
while의 경우 조건이 true가 아니면 주어진 구문을 실행하지 않지만 do while은 처음 한 번은 반드시 실행하는 구조를 가지고 있습니다.
static void Main(string[] args)
{
int i = 10;
do {
--i;
}
while(i > 10);
WriteLine(i);
}
● for
초기화, 반복조건등을 지정할 수 있는 반복문이며 다음의 구조를 갖습니다.
static void Main(string[] args)
{
for (int i = 0; i <= 100; i++) {
WriteLine(i);
}
}
for의 괄호안에는 for문의 반복을 위한 '초기화; 반복 조건; 반복식'의 형식으로 지정됩니다. 각각은 ;문자로 구분하며 처음 for문 시작 시 초기 화식을 실행하고 반복 조건을 확인해 중괄호(}}) 내부 구문을 실행합니다. 내부 구문을 실행하고 나면 반복식을 실행하고 반복 조건을 확인해 다시 내부 구문을 실행할 것인지를 판단하게 됩니다.
for문에서 '초기화;반복조건;반복식'은 ;문자만 남겨두고 모두 생략할 수 있는데(for (;;)) 이런 경우 for문은 무한으로 반복하는 무한루프를 돌게 됩니다.
● foreach
배열 또는 컬렉션 객체 등을 순회할 목적으로 만들어진 반복문입니다.
static void Main(string[] args)
{
int[] i = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
foreach(int j in i)
{
WriteLine(j);
}
}
in 절을 기준으로 왼쪽에는 배열에서 추출한 요소가 들어갈 변수를, 오른쪽에는 배열이나 컬렉션 변수를 놓습니다. 그러면 배열/컬렉션 요소에서 처음부터 순서대로 알아서 값을 추출해 왼쪽 변수에 할당하고 괄호 안의 구문을 실행합니다. 배열이나 컬렉션 객체에서 더 이상 추출할 요소가 없으면 반복문은 자동 종료됩니다.
3. 점프 문
점프 문은 프로그램 실행을 중단하거나 다른 곳으로 실행을 이동시키기 위한 목적으로 종종 사용됩니다.
● return
특정 값을 반환하고 프로그램 또는 특정 메서드의 실행을 중지합니다.
static void Main(string[] args)
{
int i = 0;
while (true) {
if (i == 10)
return;
WriteLine(i);
++i;
}
WriteLine("완료");
}
예제에서 i의 값이 10이 되면 return 문을 실행하게 되고 프로그램의 동작은 중지할 것입니다. 만약 특정 값이 반환이 필요하다면 'return 값'의 형식으로 return을 사용할 수 있는데 보통 특정 메서드에서 다른 메서드로 어떠한 값을 전달할 때 많이 사용되는 방법입니다.
만약 아무런 값도 지정하지 않으면 실행을 중지하는 역할만 수행하지만 특정 값을 반환하도록 지정된 메서드 안에서 사용되는 경우라면 해당 형식의 반환 값 지정은 생략할 수 없습니다.
● break
return은 실행 자체를 중지하지만 break는 특정 블록 안에서 해당 영역을 빠져나오도록 합니다.
static void Main(string[] args)
{
int i = 0;
while (true) {
if (i == 10)
break;
WriteLine(i);
++i;
}
WriteLine("완료");
}
이 예제는 위의 return예제에서 return을 break로만 바꾼 것입니다. return에서는 실행 자체를 종료하기 때문에 return이하는 실행될 수 없었습니다. 그래서 "완료"라는 내용도 표시할 수 없었는데 break는 현재 while문 영역을 벗어난 후 남은 실행 구문을 모두 처리하기 때문에 "완료"라는 메시지를 볼 수 있습니다.
● continue
continue 일시적으로 실행을 skip 하고자 하는 경우에 사용합니다.
static void Main(string[] args)
{
int i = 0;
while (i < 10) {
++i;
if (i == 5)
continue;
WriteLine(i);
}
}
break는 해당 반복문을 벗어나지만 continue문은 처리가 더 이상 진행되지 않도록 막고 다음 반복문을 계속 수행하도록 합니다. 따라서 위 예제는 i가 5일때만 화면에 표시하지 않고 넘어가게 됩니다.
● throw
예외를 발생하고 프로그램의 실행을 중지합니다.
static void Main(string[] args)
{
int i = 0;
while (i < 10) {
++i;
if (i == 5)
throw new Exception("i가 5인 경우는 처리할 수 없습니다.");
WriteLine(i);
}
}
프로그램 실행이 더이상 진행될 수 없고 사용자에게 중대한 오류임을 알려야 하는 경우 사용합니다.
● goto
지정된 특정 레이블로 처리를 이동합니다.
static void Main(string[] args)
{
int i = 0;
while (i < 10) {
++i;
if (i == 5)
goto myLabel;
WriteLine(i);
}
myLabel:
WriteLine("i는 5입니다.");
}
예제에서 goto의 레이블은 myLabel로 하였으나 이름은 임의로 지정할 수 있습니다.
'.NET > C#' 카테고리의 다른 글
[C#] 클래스(Class) (0) | 2021.10.06 |
---|---|
[C#] 메서드 (0) | 2021.09.27 |
[C#] 연산자 (0) | 2021.09.23 |
[C#] 데이터 (2) | 2021.09.23 |
[C#] 시작하기 (0) | 2021.01.13 |