C#예외 처리 모범 사례

16267 단어 exceptiondotnetcsharp
나는 과학 기술 업계에서 곧 20주년이 된다.최근 몇 년 동안, 나는 이상을 처리할 때 거의 모든 반모드를 보았다. (게다가 나 개인도 잘못을 저질렀다.)이 기사는 C#의 예외 사항을 처리할 때 수행한 모범 사례를 모았습니다.

다시 이상 던지지 마세요.
나는 이 일을 한 번 또 한 번 보았다.사람들은 오류 처리 과정에서 원시 창고 추적이 신기하게 사라지는 것에 대해 곤혹스러움을 느꼈다.이것은 통상적으로 원시 이상을 던지는 것이 아니라 다시 이상을 던지는 것이다.한 가지 예를 살펴보겠습니다. 그 중에서 우리는 끼워 넣은 것이 하나 있습니다. try/catch
try
{
    try
    {
        // Call some other code thay may cause the SpecificException
    }
    catch (SpecificException specificException)
    {
        log.LogError(specificException, "Specific error");
    }

    // Call some other code
}
catch (Exception exception)
{
    log.LogError(exception, "General erro");
}
이미 알고 계신 바와 같이 내부try/catch에서 이상을 포획하고 기록하며 삼킵니다.전역 SpecificException 블록을 던지기 catch 하려면 창고에서 던져야 합니다.너는 이렇게 할 수 있다.
catch (SpecificException specificException)
{
    // ...
    throw specificException;
}
또는 이것:
catch (SpecificException specificException)
{
    // ...
    throw;
}
여기의 주요 차이점은 첫 번째 예시를 다시 던지는 것이다. SpecificException 이것은 원시 이상 창고 추적 리셋을 초래하고, 두 번째 예시는 원시 이상의 모든 세부 사항만 보존한다.너는 거의 항상 두 번째 예를 쓰고 싶어한다.

장식 예외
나는 이런 습관이 매우 적게 사용되는 것을 보았다.모든 예외가 확장되었습니다. Exception 사전이 있습니다.사전은 오류에 대한 추가 정보를 포함하는 데 사용할 수 있습니다.이 정보가 로그에 표시되는지 여부는 로그 프레임워크와 저장에 달려 있습니다.엠마를 위해서.ioData 항목은elmah의 데이터 옵션 카드에서 볼 수 있습니다.이오.Data 사전에 정보를 포함하려면 키/값 쌍을 추가합니다.
var exception = new Exception("En error happened");
exception.Data.Add("user", Thread.CurrentPrincipal.Identity.Name);
throw exception;
이 예시에서, 나는 Data 이라는 키를 추가했는데, 이 키의 잠재적인 사용자 이름은 라인에 저장된다.
외부 코드에서 발생하는 이상을 수정할 수도 있습니다.하나 추가user:
try
{
    service.SomeCall();
}
catch (Exception e)
{
    e.Data.Add("user", Thread.CurrentPrincipal.Identity.Name);
    throw;
}
코드 포획try/catch 방법으로 인한 모든 이상은 이상에 사용자 이름을 포함합니다.SomeCall 키워드를 throw 블록에 추가하면 원시 이상은 창고의 더 위에 던져집니다.

우선 더 구체적인 이상을 포획하다
너는 네가 유사한 코드를 가지고 있다는 것을 안다.
try
{
    File.WriteAllText(path, contents);
}
catch (Exception e)
{
    logger.Error(e);
}
포획catch만 하고 이를 선택한 로그 프레임워크에 기록하면 신속하게 작업을 실현하고 완성할 수 있다.대다수의 도서관이 다 있다.NET는 코드 라이브러리에 유사한 패턴이 있을 수도 있는 일련의 다른 이상을 던질 수 있습니다.여러 개의 이상을 포획하는 것은 (가장 특정한 오류부터 가장 불특정한 오류까지) 모든 종류를 어떻게 계속 처리하고 싶은지 구분하는 좋은 방법이다.
다음 예제에서는 예상되는 예외와 각 예외 유형을 처리하는 방법에 대해 명확하게 설명합니다.
try
{
    File.WriteAllText(path, contents);
}
catch (ArgumentException ae)
{
    Message.Show("Invalid path");
}
catch (DirectoryNotFoundException dnfe)
{
    Message.Show("Directory not found");
}
catch (Exception e)
{
    var supportId = Guid.NewGuid();
    e.Data.Add("Support id", supportId);
    logger.Error(e);
    Message.Show($"Please contact support with id: {supportId}");
}
포획 범위Exception 이전에 포획ArgumentExceptionDirectoryNotFoundException를 통해 사용자에게 전용 메시지를 표시할 수 있습니다.이 장면에서 나는 이상을 기록하지 않을 것이다. 왜냐하면 사용자가 오류를 신속하게 복구할 수 있기 때문이다.Exception의 경우 지원 id를 생성하여 오류를 기록하고 (앞에서 보듯이decorators를 사용합니다) 사용자에게 메시지를 표시합니다.
위의 코드는 이상 순서를 설명하는 데 사용되지만 이러한 이상을 사용하여 흐름을 제어하는 것은 좋지 않은 방법입니다.다음 모범 사례에 대한 완벽한 설명입니다.

예외를 피하다
예외를 피하면 분명히 들릴 수 있다.그러나 많은 이상을 던지는 방법은 방어적인 프로그래밍을 통해 피할 수 있다.
가장 흔히 볼 수 있는 예외 중 하나는 Exception이다.어떤 경우,null을 허용하기를 원하지만,null을 검사하는 것을 잊어버릴 수도 있습니다.다음은 플롯NullReferenceException의 예입니다.
Address a = null;
var city = a.City;
방문NullReferenceException에서 이상이 발생하지만 계속 놀아주세요. a가 매개 변수로 제공된다고 상상해 보세요.
도시에서a 값을 사용할 수 있도록 하려면 null 조건 연산자를 사용하여 이상을 피할 수 있습니다.
Address a = null;
var city = a?.City;
방문null 시 추가?를 통해 C# 자동 처리 주소가 a인 경우.이 경우 null 변수는 값city을 얻는다.
또 다른 흔히 볼 수 있는 이상 예는 숫자나 부울 값을 분석할 때이다.다음 예제에서는 하나null를 내보냅니다.
var i = int.Parse("invalid");
FormatException 문자열을 정수로 해석할 수 없습니다.invalid와는 달리 try/catch는 1000번 이상 사용할 수 있는 기발한 방법을 제공합니다.
if (int.TryParse("invalid", out int i))
{
}
intinvalid로 해석될 수 있다면 intTryParse로 되돌아와 해석된 값을 true 변수에 넣는다.또 다른 예외를 피했다.

사용자 정의 예외 만들기
자바 프로그래머로서의 나의 세월을 회상하면 (.NET 테스트 버전으로 돌아왔을 때) 재미있다.모든 내용을 위한 사용자 정의 이상을 만들었습니다.아마도 자바에서 더 현저한 이상이 이루어졌기 때문일 것이다. 그러나 나는 이런 모델이 자바에서 자주 반복되는 것을 볼 수 없다.NET 및 C#.사용자 정의 이상을 만들면 앞에서 보듯이 특정한 이상을 더욱 잘 포착할 수 있습니다.레코더가 i 사전을 지원하는 경우, 사용자 정의 변수를 사용하여 이상을 수정할 수 있으며, 걱정하지 않아도 된다.
public class MyVerySpecializedException : Exception
{
    public MyVerySpecializedException() : base() {}
    public MyVerySpecializedException(string message) : base(message) {}
    public MyVerySpecializedException(string message, Exception inner) : base(message, inner) {}

    public int Status { get; set; }
}
Data 클래스는 모든 이상 클래스가 가지고 있어야 할 세 가지 구조 함수를 실현했다.그 밖에 나는 MyVerySpecializedException 속성을 추가 데이터의 예로 추가했다.이렇게 하면 다음과 같은 코드를 작성할 수 있습니다.
try
{
    service.SomeCall();
}
catch (MyVerySpecializedException e) when (e.Status == 500)
{
    // Do something specific for Status 500
}
catch (MyVerySpecializedException ex)
{
    // Do something general
}
Status 키워드를 사용하여 when 속성의 값이 MyVerySpecializedException일 때 포착할 수 있습니다Status.기타 모든 상황은 총 포획량500으로 끝납니다.

로그 예외
이것은 매우 명백한 것 같다.그러나 이 모드를 사용할 때, 나는 뒤의 몇 줄에서 실패한 코드를 너무 많이 보았다.
try
{
    service.SomeCall();
}
catch
{
    // Ignored
}
미포획과 포획의 이상을 기록하는 것은 최소한 사용자를 위해 할 수 있는 일입니다.사용자가 지원에 연락하는 것보다 더 나쁜 것은 없습니다. 오류가 발생했고 무슨 일이 일어났는지 모릅니다.일지기록이 그걸 해줄 거야.
NLog과 Serilog 등 여러 가지 훌륭한 로그 프레임워크가 있습니다.니가 ASP라면NET(Core) 웹 개발자는 elmah를 사용하여 캡처되지 않은 이상을 자동으로 기록할 수 있습니다.io 또는 기타 사용 가능한 도구 중 하나입니다.

당신의 사용자는 더 적은 오류를 좋아합니까?
엠마.io는 간단한 오류 기록과 정상적인 운행 시간 모니터링 서비스이다.그물모든 사람에 대한 지지를 통해 자신의 잘못을 다시 컨트롤하다.NET 웹 및 로그 프레임워크
➡️ Error Monitoring for .NET Web Applications ⬅️
이 문장은 처음으로 느릅나무에 나타났다.io 블로그 주소https://blog.elmah.io/csharp-exception-handling-best-practices/

좋은 웹페이지 즐겨찾기