갓똥
나는야 프로그래머
갓똥
전체 방문자
오늘
어제
  • 분류 전체보기 (186)
    • 프로그래밍 (146)
      • 자바 (9)
      • 안드로이드 (2)
      • 유니티 (20)
      • C++ (38)
      • C# (56)
      • HTML (2)
      • 파이썬 (3)
      • 자료구조 (2)
      • 알고리즘 (0)
      • 문제풀이 (4)
      • 디자인 패턴 (7)
      • 카카오톡 봇 (1)
      • 엑셀 (1)
      • 기타 (1)
    • 게임 (21)
      • 테일즈위버 (0)
      • 카이로소프트 (1)
      • 순위 (19)
      • 기타 (1)
    • 일상 (13)
      • 카페 (1)
      • 방탈출 (12)
    • 기타 (6)
      • 웃긴자료 (5)

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

태그

  • 2020년 게임 매출
  • 전세계 게임 매출
  • Unity Graph
  • c# coroutine
  • 글로벌게임매출
  • 게임 매출 순위
  • 유니티 골드그래프
  • c# delegate
  • C++
  • c# Thread
  • pc게임 순위
  • 유니티 그래프
  • 전세계게임매출순위
  • 강남 방탈출
  • pc 게임 순위
  • C++ virtual
  • 자바
  • c# unboxing
  • C++ 소멸자
  • c# collection
  • 게임 디자인 패턴
  • c# 코루틴
  • C# 예외 처리
  • 알고리즘
  • 게임매출순위
  • 유니티 그래프 그리기
  • C# boxing
  • C++ 상속
  • 모바일 게임 순위
  • 롤 골드그래프

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
갓똥

나는야 프로그래머

[C#] 예외 필터 (exception filter)
프로그래밍/C#

[C#] 예외 필터 (exception filter)

2020. 4. 20. 18:38
728x90
반응형

1. 핵심 정리

using System;
using System.Net;

class Program {
    static void Main() {
        WebClient wc = new WebClient();
        try {
            stirng s = wc.DownloadString("http://wwww.nnaver.ccom");
        }
        catch(WebException e) {
            if(e.Status == WebExceptionStatus.NameResolutionFailure)
                Console.WriteLine("URL 입력 에러");
            else if(e.Status == WebExceptionStatus.Timeout)
                Console.WriteLine("시간 초과");
            else
                Console.WriteLine("다른 문제");
        }
        catch(Exception e) {
        }
        wc.Dispose();
    }
}

 

웹 클라이언트 객체를 만들어 특정 웹사이트의 문자를 꺼내오려했는데
오타가 나서 예외가 발생하는 상황이다.
앞서 보았던것은 입력값 오류, null, 스레드간 동시 호출의 예외가 있었는데
각 항목별로 조금 더 자세하게 받아올 수 있다.
Exception 클래스의 멤버로 Status가 있는데 이를 이용한 방법이다.
각 예외에 대한 Status도 존재한다.
정의로 이동해보면 enum타입으로 있다.

각 예외에 대해 다르게 작성할 수 있어서 위와 같이 URL오류, 시간 초과의 문제로 나누었다.
하지만 접속 실패, 기타 필요한 예외 처리를 하면 할수록 코드가 길어질텐데 
이럴 때 예외 필터란 것을 쓸 수 있다.

 

using System;
using System.Net;

class Program {
    static void Main() {
        WebClient wc = new WebClient();
        try {
            stirng s = wc.DownloadString("http://wwww.nnaver.ccom");
        }
        catch(WebException e) when(e.Status == WebExceptionStatus.NameResolutionFailuer) {
            Console.WriteLine("URL 입력 에러");
        }
        catch(WebException e) when(e.Status == WebExceptionStatus.Timeout) {
            Console.WriteLine("시간 초과");
        }
        
        catch(Exception e) {
        }
        wc.Dispose();
    }
}

 

필요한 예외를 골라 참일 경우 해당 catch문을 실행한다.
C# 6.0부터 지원하는 문법이다.

 


2. 활용

using System;

class Server {
    public void Connect() {
        throw new TimeoutException();
    }
}

class Program {
    static void Foo() {
        Server wc = new Server();
        
        try {
            wc.Connect();
        }
        catch(Exception e) when(Logging(e)) {
            Console.WriteLine("Foo catch");
        }
    }
    
    static bool Logging(Exception e) {
        Console.WriteLine($"LOG : {e.Message}");
        return false;
    }
    
    static void Main() {
        try {
            Foo();
        }
        catch (Exception e) {
            Console.WriteLine("처리");
        }
    }
}

 

위 코드에서 예외 필터의 활용 사례를 볼 수 있다.
상황 자체는 서버에 접속하려 하지만 무조건 예외를 뱉게 되어있다.
예외에 대한 처리가 Foo함수와 Main함수에 있는데
Foo에서 먼저 처리를 하고 Main에서 처리를 할 것이다.
근데 자세히 보면 Foo에서는 예외가 발생해도 catch문을 실행하지 않는다.
왜냐하면 예외 필터는 해당 예외가 참일 때 실행되는데 Logging함수는 항상 false를 뱉는다.
따라서 catch문을 실행하지 않는다.
그럼 왜 이렇게 썼을까?
답은 함수이름과 같이 로깅을 위해 쓴 것이다.
catch문을 실행하게 되면 약간의 성능저하가 발생되는데 로그만 찍어주고 catch문에 들어가지 않으므로
성능저하를 줄일 수 있다.

 ① 성능 저하를 줄이기 위해

 

using System;

class Server {
    public void Connect() {
        throw new TimeoutException();
    }
}

class Program {
    static void Foo() {
        int retryCount = 0;
        bool bSuccess = false;
        
        Server wc = new Server();
        
        while(bSuccess == false) {
            try {
                wc.Connect();
                bSuccess = true;
            }
            catch(TimeoutException e) {
                if(++retryCount < 4)
                    Console.WriteLine("다시 시도");
                else
                    throw;
            }
        }
    }
    
    static void Main() {
        try {
            Foo();
        }
        catch (Exception e) {
            Console.WriteLine("예외 처리");
        }
    }
}

 

다시 이전 코드와 비슷하지만 조금 다른 코드이다.
bSuccess로 접속 여부를 판단하여 접속이 안된다면 로그를 찍고 다시 접속을 시도한다.
3번의 실패가 일어나게되면 Main으로 예외를 던져 처리하게 되는 코드이다.
충분히 있을 수 있는 코드인데 이 코드도 문제는 catch를 총 4번 처리한다는 것이다.
앞서 말했듯이 catch는 약간의 성능 저하가 생기므로 되도록 횟수를 줄이는 것이 좋다.
이것도 예외 필터를 사용해 해결 가능하다.

 

using System;

class Server {
    public void Connect() {
        throw new TimeoutException();
    }
}

class Program {
    static void Foo() {
        int retryCount = 0;
        bool bSuccess = false;
        
        Server wc = new Server();
        
        while(bSuccess == false) {
            try {
                wc.Connect();
                bSuccess = true;
            }
            catch(TimeoutException e) when(++retryCount < 4) {
                Console.WriteLine("다시 시도");
            }
        }
    }
    
    static void Main() {
        try {
            Foo();
        }
        catch (Exception e) {
            Console.WriteLine("예외 처리");
        }
    }
}

 

예외 필터가 참일 경우만 실행되는 것을 이용하여 위와 같이 할 수 있다.
728x90
반응형

'프로그래밍 > C#' 카테고리의 다른 글

[C#] 컬렉션 (Collection)  (0) 2020.04.23
[C#] try ~ finally  (0) 2020.04.21
[C#] 예외를 처리하는 방법 (catch, Exception, rethrow)  (0) 2020.04.20
[C#] 예외 처리  (0) 2020.04.17
[C#] 람다 표현식 (Lambda Expression)  (0) 2020.04.16
    '프로그래밍/C#' 카테고리의 다른 글
    • [C#] 컬렉션 (Collection)
    • [C#] try ~ finally
    • [C#] 예외를 처리하는 방법 (catch, Exception, rethrow)
    • [C#] 예외 처리
    갓똥
    갓똥
    공부하며 알아가는 내용을 정리해 봅니다.

    티스토리툴바