상세 컨텐츠

본문 제목

[C#] 예외처리

.NET/C#

by 클리엘 클리엘 2021. 2. 25. 13:34

본문

728x90

프로그램이 정상적인 코드를 통해 실행되는 과정에서 예기치 않은 상황으로 인해 실행이 중단되는 것을 예외라고 합니다.

 

아래 예제에서 배열은 0부터 2까지 밖에 없으나 3번째 인덱스에 값을 넣으려고 시도합니다.

static void Main(string[] args)
{
	int[] i = new int[] {1, 2, 3};

	i[3] = 4;

	Console.WriteLine($"{i[1]}");
}

배열 처리과정에서 발생한 예외는 main() 메서드 안에서 처리할 수 없으므로(예외를 받아서 처리해줄 코드가 없으므로) main() 메서드를 호출한 상위 메서드를 찾게 됩니다. 하지만 main()은 main()을 호출한 상위 메서드가 없으므로 예외를 다시 CLR에게 넘기게 되고 CLR은 전달받은 예외 정보를 사용자에게 전달하고 프로그램을 중지하게 됩니다. 프로그램은 i[3] = 4 부터 오류를 일으키고 Console을 통해 값을 출력하려는 나머지 코드는 당연히 실행되지 않습니다.

 

프로그램에서 예외를 처리하는 기본적인 방법은 try ~ catch를 이용하는 것입니다.

static void Main(string[] args)
{
	int[] i = new int[] {1, 2, 3};

	try {
		i[3] = 4;
	}
	catch (Exception e) {
		Console.WriteLine($"Error : {e.Message}");
	}

	Console.WriteLine($"{i[1]}");
}

try안에서 예외가 발생하면 catch로 처리를 넘기게 됩니다. 기존과 다른점은 프로그램 실행이 중단되지 않고 정해진대로 예외가 처리된 다음 실행을 계속 진행한다는 것입니다.

int[] i = new int[] {1, 2, 3};

try {
	i[3] = 4;
}
catch (Exception e) {
	Console.WriteLine($"Error : {e.Message}");
}
finally {
	//완료처리
}

Console.WriteLine($"{i[1]}");

try ~ catch에는 finally도 추가할 수 있는데 finally안의 구문은 예외가 있든 없든 무조건 실행합니다. 심지어 try안에서 return을 통해 메서드를 종료하더라도 return이후에 finally가 곧장 실행됩니다.

 

예외는 별다른 예외클래스를 지정하지 않으면 System.Exception형식으로 받게 됩니다. 특정 예외상황에서만 다른 처리가 필요하다면 해당 예외상황에 맞는 클래스를 지정해야 합니다.

static void Main(string[] args)
{
	int[] i = new int[] {1, 2, 3};

	try {
		i[3] = 4;
	}
	catch (IndexOutOfRangeException ie) {
		Console.WriteLine($"Array Error : {ie.Message}");
	}
	catch (Exception e) {
		Console.WriteLine($"Error : {e.Message}");
	}

	Console.WriteLine($"{i[1]}");
}

위 예제에서 사용된 IndexOutOfRangeException은 배열의 인덱스를 벗어나는 경우의 예외입니다. 따라서 첫 번째 Catch로 예외가 전달되고 Array Error... 메시지를 출력합니다.

 

예외는 필요하다면 아래와 같은 방법으로 예외를 던져줄 수 있습니다.

try {
	int idx = 3;

	if (i.Length <= idx)
		throw new Exception("오류");
		
	i[3] = 4;
}
catch (IndexOutOfRangeException ie) {
	Console.WriteLine($"Array Error : {ie.Message}");
}
catch (Exception e) {
	Console.WriteLine($"Error : {e.Message}");
}

경우에 따라 문이 아닌 식으로로 예외구현이 가능합니다.

int[] i = new int[] {1, 2, 3};

try {
	int idx = 3;

	i[(idx <= 2 ? idx : throw new Exception("예외"))] = 4;
}
catch (IndexOutOfRangeException ie) {
	Console.WriteLine($"Array Error : {ie.Message}");
}
catch (Exception e) {
	Console.WriteLine($"Error : {e.Message}");
}

	Console.WriteLine($"{i[1]}");
}

한발 더 나아가 아예 예외클래스 자체를 직접 생성할 수도 있습니다.

class MyException : Exception
{
	public MyException(string message) : base(message)
	{
	}

	public int Idx
	{
		get;
		set;
	}
}

사용자 정의 예외는 Exception클래스의 파생 클래스여야 하며 생성자를 통해 오류 메시지를 받고 속성으로 예외 인스턴스에서 원하는 값을 표시할 수 있습니다.

int[] i = new int[] {1, 2, 3};

try {
	int idx = 3;

	i[(idx <= 2 ? idx : throw new MyException("MyError") { Idx = idx })] = 4;
}
catch (MyException ie) {
	Console.WriteLine($"Array Error : {ie.Message}, index : {ie.Idx}");
}
catch (Exception e) {
	Console.WriteLine($"Error : {e.Message}");
}

	Console.WriteLine($"{i[1]}");
}

또한 예외처리단게에서는 별도의 필터를 통해 예외가 발생할 수 있는 조건을 분리할 수도 있습니다.

int[] i = new int[] {1, 2, 3};

try {
	int idx = 3;

	i[(idx <= 2 ? idx : throw new MyException("MyError") { Idx = idx })] = 4;
}
catch (MyException ie) when (ie.Idx == 2) {
	Console.WriteLine($"index : 2");
}
catch (MyException ie2) {
	Console.WriteLine($"Array Error : {ie2.Message}, index : {ie2.Idx}");
}
catch (Exception e) {
	Console.WriteLine($"Error : {e.Message}");
}

	Console.WriteLine($"{i[1]}");
}

예외에서 첫번째 MyException에서는 ie의 Idx값이 2인 경우에만 걸리도록 하였으며 그 외의 값인 경우 2번째나 3번째 예외처리로 이동할 것입니다.

728x90

'.NET > C#' 카테고리의 다른 글

[C#] 이벤트(Event)  (0) 2021.04.12
[C#] 람다식  (0) 2021.04.06
[C#] 예외처리  (0) 2021.02.25
[C#] 일반화  (0) 2021.02.11
[C#] 배열및 컬렉션과 인덱서활용 그리고 나열하기  (0) 2021.02.08
[C#] 프로퍼티  (0) 2021.02.01

태그

관련글 더보기

댓글 영역