728x90
반응형
0. 개요
using System;
public static class FileManager {
public static int CopyFile(string srcFileName, string dstFileName) {
// ...
return 100;
}
}
class Program {
static void Main() {
FileManager.CopyFile("C:\\a.txt", "D:\\b.txt");
}
}
위와 같이 파일 이름을 인자로 받아 앞의 인자의 내용을 뒤의 인자로 복사하는 코드가 있다고 해보자.
복사를 하면 복사한 양을 리턴해주게끔까지 해놓았다.
그런데 이러한 코드가 항상 성공한다는 보장이 없다.
사용자가 이름을 실수할 수도 있고, 접근 권한이 없을 수도 있는 등 실패할 가능성도 있다.
이럴 때 실패로 생긴 오류를 어떻게 처리할지에 대해 생각해보자.
보통 소프트웨어에서 이러한 오류에 대처하는 방법이 3가지 있다.
① 메소드(함수)가 실패 했음을 호출자에게 알려주는 방법
=> 1. 반환값을 사용해서 오류를 전달
=> 2. Out 파라미터를 사용하는 방법
=> 3. 예외를 사용하는 방법
1. 반환값을 사용해서 오류를 전달
using System;
public static class FileManager {
public static int CopyFile(string srcFileName, string dstFileName) {
// ...
return -1;
}
}
class Program {
static void Main() {
int ret = FileManager.CopyFile("C:\\a.txt", "D:\\b.txt");
if(ret < 0) {
// ...
}
// FileManager.DeleteFile("C:\\a.txt");
// FileManager.OpenFile("D:\\b.txt");
}
}
파일 복사에 실패 했을 때 반환값을 -1로 하여 실패를 검사하는 코드가 추가되었다.
복사에 성공했다면 0보다는 클테니 확실하게 성공 실패 여부를 알 수 있다.
하지만 이 방법에는 몇 가지 단점이 있다.
먼저, 반환 값과 오류가 모호하다. 위의 코드는 그나마 명확한 편인데 연산한 값이 -1이 될 경우도 있을 것이다.
둘째, 어떻게 실패했는지 알 수가 없다. 실패만 알 뿐 권한문제, 입력 실수 등 자세히 알 수 없다.
셋째, 실패했을 때의 코드를 강제할 수 없다. 사용자가 주석처리해버린다면 실패시에도 처리를 하지 않는다.
넷째, 코드의 흐름속에 오류 처리 코드가 섞여 있어 헷갈린다.
위 방식은 확실히 많이 사용하며 간편하지만 문제가 있긴 하다.
정리하면 아래와 같다.
① 특징(단점)
=> 반환 값과 오류가 모호
=> 오류에 대한 자세한 정보를 알려줄 수 없음
=> 사용자가 함수 실패를 반드시 처리하도록 강제할 수 없다.
=> 정상적인 흐름의 코드와 오류를 처리하는 코드가 분리되지 않고 섞여 있다.
2. out 파라미터 활용
using System;
public static class FileManager {
public static int CopyFile(string srcFileName, string dstFileName) {
// ...
return -1;
}
}
class Program {
static void Main() {
int ret = FileManager.CopyFile("C:\\a.txt", "D:\\b.txt");
if(ret < 0) {
// ...
}
}
}
다음은 out파라미터를 사용할 것이다.
이전 방법의 문제 중 하나가 메소드의 반환값이 두 가지 의미로 사용된다는 것이였다.
하나는 진짜 반환값으로 쓸 수도 있고, 실패에 대한 값을 나타낸다.
그래서 의미를 나눠보기로 했다.
① 반환 값과 오류의 전달을 분리
using System;
public static class FileManager {
public static bool CopyFile(string srcFileName, string dstFileName, out int len) {
// ...
len = 100; // 복사한 사이즈
return false;
}
}
class Program {
static void Main() {
int len;
bool ret = FileManager.CopyFile("C:\\a.txt", "D:\\b.txt", out len);
if(ret == false) {
// ...
}
}
}
위는 out파라미터를 사용하게 수정한 코드이다.
이제 len파라미터가 추가되어 복사한 양을 알 수 있고
성공, 실패에 대해 true, false로 보다 명확하게 알 수 있게 되었다.
이 방법에 대한것도 장단점이 있다.
위에서 말한 것과 같이 반환값의 의미가 분리되었다.
그리고 위에선 bool로 했지만 다시 int로 하여 어디서 오류가 발생했는지 정확하게 알 수 있다.
위 out파라미터 기술을 널리 사용한게 마이크로소프트의 COM기술이였다.
반대로 단점은 여전히 사용자에게 강제할 수 없는 부분이 있고
여전히 코드가 섞이기 때문에 분리가 되지 않고
사용자가 out파라미터를 써야하기 때문에 쓰는 입장에서 까다롭다.
위 방법이 문제가 있기에 안쓰이는건 아니다.
앞선 방법도 여전히 널리 쓰이고 있고 이 방법은
C#에서 try에서 쓰이고 있다. (ex. TryParse)
② C# 언어에서 접두어가 Try...로 시작하는 메소드가 이 방식을 사용
string s = "10";
int num;
bool b = int.TryParse(s, out num);
// 문자열을 정수로 변환
// 성공 실패 여부는 b로 성공 시 값은 num으로
3. 예외(Exception)
using System;
public static class FileManager {
public static int CopyFile(string srcFileName, string dstFileName) {
// ...
// if(실패)
throw new Exception("파일 접근 권한 없음");
return 100;
}
}
class Program {
static void Main() {
FileManager.CopyFile("C:\\a.txt", "D:\\b.txt");
}
}
이번엔 throw를 이용해서 예외를 처리해보자. (위의 코드는 일단 실패 상황을 가정했다.)
throw라는 단어의 의미때문에 보통 예외를 던진다고 표현한다.
일단 위와 같이 throw를 통해 예외 상황을 던져준다고 하자.
이렇게 되면 오류의 전달과 메소드의 반환값이 완전히 분리되는 장점이 있다.
또한 Exception클래스를 이용해 세부 정보도 알 수 있다.
또 위의 코드와 같이 예외를 처리하지 않고 실행하면 프로그램이 종료되는 것을 볼 수 있다.
이로써 예외 처리를 강제할 수 있다.
예외 처리는 try ~ catch문을 사용해서 오류를 처리한다.
① 메소드가 실패 하면
=> throw 키워드를 사용해서 예외를 던진다.
=> 오류의 전달과 메소드의 반환 값이 완전히 분리된다.
=> Exception 클래스의 다양한 속성과 메소드 등을 이용해서 오류에 대한 다양한 정보를 전달 가능.
② 메소드에서 예외가 발생할 때
=> 예외를 처리하지 않으면 오류 메시지 발생 후 프로그램 종료
=> try ~ catch 문을 사용해서 오류를 처리해야 한다.
using System;
public static class FileManager {
public static int CopyFile(string srcFileName, string dstFileName) {
// ...
// if(실패)
throw new Exception("파일 접근 권한 없음");
return 100;
}
}
class Program {
static void Main() {
try {
FileManager.CopyFile("C:\\a.txt", "D:\\b.txt");
Console.WriteLine("이후 정상 코드 실행");
Console.WriteLine("기존파일삭제/신규파일오픈");
}
catch(Exception e) {
Console.WriteLine(e.Message);
}
Console.WriteLine("이후 코드 실행");
}
}
③ 특징
=> 오류 처리에 대한 강제성이 생긴다.
=> 정상적인 흐름의 코드와 오류 처리를 위한 코드를 분리할 수 있다.
728x90
반응형
'프로그래밍 > C#' 카테고리의 다른 글
[C#] 예외 필터 (exception filter) (0) | 2020.04.20 |
---|---|
[C#] 예외를 처리하는 방법 (catch, Exception, rethrow) (0) | 2020.04.20 |
[C#] 람다 표현식 (Lambda Expression) (0) | 2020.04.16 |
[C#] Action, Func (0) | 2020.04.16 |
[C#] event (0) | 2020.04.08 |