[Effective C#] 45. 메서드가 실패했음을 알리기 위해서 예외를 이용하라
- C#/Effective C# 책 정리
- 2021. 11. 30. 19:48
1. 참조
- Effective C# 개정판 3판
- https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/try-catch
- https://stackoverflow.com/questions/444654/exceptions-vs-return-codes-do-we-lose-something-while-gaining-something-else
2. 소개
- 메서드가 요청된 작업을 제대로 수행할 수 없는 경우 예외를 발생시켜 실패가 발생했음을 알려야 합니다.
3. 반환 코드
- 반환 코드의 경우 메서드의 원형에 영향을 미칩니다.
- 계산의 결과를 나타내는 용도로 주로 사용되므로 오류가 발생했다는 사실 이외의 추가적인 정보를 전달하기가 어렵습니다.
using System;
namespace interfaceTest
{
public enum FOO_RESULT
{
OK = 0,
ERROR = 1,
FOO = 2,
BAR = 3
}
class Program
{
static void Main(string[] args)
{
for(int index = 0; index < 10; index++)
{
Console.WriteLine($"{DoSomeEnum(index)}");
}
}
public static FOO_RESULT DoSomeEnum(int number)
{
/* 임의의 작업 */
if (number == 5)
{
return FOO_RESULT.ERROR;
}
/* 임의의 작업 */
if (number == 4)
{
return FOO_RESULT.FOO;
}
/* 임의의 작업 */
if (number == 3)
{
return FOO_RESULT.FOO;
}
/* 임의의 작업 */
return FOO_RESULT.OK;
}
}
}
OK
OK
OK
FOO
FOO
ERROR
OK
OK
OK
OK
4. 예외
- 예외를 이용하는 방식은 클래스 타입이므로 개발자가 자신만의 예외 타입을 파생시킬 수 있으며 오류에 대한 추가적인 정보를 전달할 수 있습니다.
- 콜 스택을 통해서 적절한 catch문이 구성된 위치까지 전파됩니다.
- 적절한 catch문이 포함되어있지 않다면 응용프로그램이 종료되니 예외는 쉽게 무시하기 어렵습니다.
using System;
namespace Chapter45
{
class Program
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException(paramName: nameof(s), message: "Parameter can't be null");
}
}
static void Main(string[] args)
{
try
{
string s = null;
ProcessString(s);
}
// Most specific:
catch (ArgumentNullException e)
{
Console.WriteLine("{0} First exception caught.", e);
}
// Least specific:
catch (Exception e)
{
Console.WriteLine("{0} Second exception caught.", e);
}
}
}
}
System.ArgumentNullException: Parameter can't be null (Parameter 's')
at Chapter45.Program.ProcessString(String s) in D:\withcommunity\withcommunity\src\effectivecsharp3\Chapter45\Chapter45\Chapter45\Program.cs:line 11
at Chapter45.Program.Main(String[] args) in D:\withcommunity\withcommunity\src\effectivecsharp3\Chapter45\Chapter45\Chapter45\Program.cs:line 20 First exception caught.
5. 사전에 예외 검사하기
- 예외를 처리하는 작업은 일반적인 메서드 호출보다 시간이 많이 걸립니다.
- 특정 작업을 수행하기 전에 실패할 가능성이 있는지 확인하는 편이 좋습니다.
5.1 잘못 사용된 예외처리
// 이런 방법은 사용하지 말라.
DoesWorkThatMightFail worker = new DoesWorkThatMightFail();
try
{
worker.DoWork();
}
catch(WorkerException e)
{
ReportErrorToUser("테스트 실패");
}
5.2 권장하는 예외처리
using System;
namespace Chapter45
{
class Program
{
static void Main(string[] args)
{
string name = "유재석";
TryDoWork(name);
Console.WriteLine();
string name2 = string.Empty;
TryDoWork(name2);
}
public static bool TryDoWork(string name)
{
if (!CheckNameConditions(name))
return false;
Work(); // 여전히 실패할 가능성은 있지만 가능성은 낮다.
return true;
}
public static bool CheckNameConditions(string name)
{
if (name == null || name.Length <= 0)
{
Console.WriteLine("이름 형식에 문제 있음!!");
return false;
}
return true;
}
public static void Work()
{
Console.WriteLine("이름 정합성 검증 성공!!");
}
}
}
이름 정합성 검증 성공!!
이름 형식에 문제 있음!!
- 위와 같이 코드를 작성하면 예외가 발생할 가능성이 있는 메서드를 호출하기 이전에 사전 조건을 테스트해볼 수 있으므로 예외로 인한 성능 저하를 피할 수 있습니다.
6. 정리
- 메서드가 실패했을 때는 언제나 예외를 발생하는 것이 좋지만, 일반적인 흐름 제어 메커니즘으로 사용해서는 안됩니다.
- 또한, 사전에 테스트할 수 있는 메서드를 같이 제공하는 것이 바람직합니다.
728x90
'C# > Effective C# 책 정리' 카테고리의 다른 글
[C#] Effective C# 7장. 델리게이트를 이용하여 콜백을 표현하라. (0) | 2023.02.23 |
---|---|
[C#] Effective C# 9장. 박싱과 언박싱을 최소화하라. (0) | 2023.02.23 |
Effective C# 개정판 3판 | 33장 필요한 시점에 필요한 요소를 생성하라. (0) | 2021.10.22 |
Effective C# 개정판 3판 | 29장 Collection 을 반환하기보다 Iterator 를 반환하는 것이 낫다. (0) | 2021.10.12 |
[Effective C# 개정판 3판] Item : 27장 인터페이스는 간략히 정의하고 기능의 확장은 확장 메서드를 사용하라 (0) | 2021.08.15 |
이 글을 공유하기