catch를 사용하기 위해 의도적으로 예외 발생


10

if...else예외 처리로 래핑 된 일반적인 경우 다음 예제와 같이 코드 복제를 피하기 위해 권장되는 방법입니까?

try
{
    if (GetDataFromServer())
    {
        return ProcessData();
    }
    else
    {
        throw new Exception();
    }
catch(Exception ex)
{
    return null;
}

대신에...

try
{
    if (GetDataFromServer())
    {
        return ProcessData();
    }
    else
    {
        return null;
    }
}
catch(Exception ex)
{
    return null;
}

약간의 성능 저하가 있음을 알고 있지만 이것이 허용 가능한 관행으로 간주되는지 궁금합니다. 현재 두 번째 방법, 특히 특정 예외를 다르게 처리 해야하는 경우-첫 번째 방법이 간단한 경우에 적합한 지 궁금합니다.


메서드가 충분히 작은 경우 else를 제거하고 trycatch 블록 외부에서 null을 반환하므로 null을 한 번만 반환하면됩니다.
Fabio Marcolini

답변:


12

흐름 제어에 예외 처리를 사용하는 것은 Microsoft에서 권장하지 않습니다.

그리고 주제에 대한 라운드 테이블을 사용할 수 있습니다.

즉, C #은 지원을 지원하며 예외가 가장 적합한 응답인지 여부에 대한 조건에 따라 다릅니다.


1
이런 종류의 일이 사건을 사용하지 않기 위해 열심히 노력하고 있다는 사실이 저를 놀라게합니다.
radarbob

@radarbob : 이벤트는 어떻게 관련되어 있습니까?

@grovesNL-catch 블록에서 특정 메소드를 호출하기 위해 특정 지점에서 예외가 발생합니까? 나에게 이벤트처럼 cks.
radarbob

@ radarbob : 이벤트가 아닙니다. 답변의 원탁 회의 링크에서 논의 된 바와 같이, 이것이 사용되는 샘플 사용 사례가 많이 있습니다.

1
@radarbob 간단히 설명하자면, 예외는 호출자가 호출 한 메소드가 처리 할 수없는 무언가가 발생했음을 호출자에게 알리는 방법으로 설계되었습니다. 그러나 이벤트를 청취해야합니다. 예외는 프로그램의 정상적인 흐름을 강제로 중단하는 것입니다. 포착되지 않은 예외는 전체 응용 프로그램을 이상 종료시킵니다.

6

이 답변 에서 설명한 것처럼 성능 적중은 무시할 수 있습니다.

성능이 문제가되지 않는다는 아이디어를 생각해 봅시다. 당신은 던지는 것 System.Exception, 단지로 실행을 이동하는 catch . 하지만 던지기 BadControlFlowThatShouldBeRewrittenException는 아마 과잉 일 것입니다.

이것을 분해하자. 우리는 :

  • 메소드 GetDataFromServer(메소드 이름은 C #에서 PascalCase 여야 함)는 예외를 발생 시키거나을 리턴 할 수 bool있습니다.
  • 결과가 true이면 실행하십시오 ProcessData.
  • 돌아 null그렇지.

이 코드가 작성되는 방법과 비슷하고 단순히 너무 많은 일을하고 있습니다. GetDataFromServer돌아 오는 bool설계 결함과 같은 모습을, 내가하는 그 방법을 기다리고있을 거라고 는 IT가 서버에서 점점 데이터 반환 , 일부 IEnumerable<SomeType>즉, 행복 경로를 반환 - 0 개 이상의 항목이 포함됩니다 N 항목 N> 0 그다지 행복하지를, path는 0 개의 항목을 반환하고 불행한 경로는 처리되지 않은 예외로 인해 발생합니다.

메소드 외모 좋아하는 것을 그 변경, 꽤 많은 - 다시는이 의미가 있는지 여부를 원래의 게시물 만 (로 컴파일하지 않을 따라서 하나 개의 출구 지점을 가지고 있기 때문에, 이야기하기 어렵다 모든 코드 경로가 값을 반환 그래서) 이것은 단지 거친 추측 일뿐입니다.

try
{
    var result = GetDataFromServer();
    return ProcessData(result);
}
catch
{
    return null;
}

여기 ProcessData에서을 반복하고 있음 result을 확인하고에 null항목이 없으면 반환 합니다 IEnumerable.

이제 왜 메서드가 반환 null됩니까? 서버가 다운 되었습니까? 쿼리에 버그가 있습니까? 연결 문자열이 잘못된 자격 증명을 사용하고 있습니까? GetDataFromServer예상치 못한 예외로 폭발 할 때마다 그것을 삼키면 서 카펫 아래로 밀어 넣고 null값을 반환 합니다. 이 경우 특정 예외를 포착하고 다른 모든 것을 기록하는 것이 좋습니다. 그렇게하면 디버깅이 훨씬 쉬워집니다.

catch예외를 포착하지 않는 일반적인 조항을 사용하면 아무것도 진단하기가 어렵습니다. 나는 이것을 최소한 대신 할 것입니다 :

catch(Exception e)
{
    return null;
}

이제 e문제가 발생했는지 최소한 깨고 검사 할 수 있습니다 .


TL; DR : 아니요, 흐름 제어에 대한 예외를 던지고 잡는 것은 좋은 생각이 아닙니다.


이 답변은 왜 내 코드를 일반적인 상태로 유지하려고 시도했는지 정확히 보여줍니다. 실제로 코드에서 만드는 모든 단일 예외를 나열하고 싶지 않았습니다. 실제 메소드 이름을 나열하고 싶지 않았습니다. 메소드 선언을 나열하고 싶지 않았습니다. 구문 제안을 원하지 않았습니다. 흐름 제어에 대한 예외를 던지는 것이 괜찮은지에 대한 단일 질문이 있었으며 B2K가 신속하게 대답했습니다. 나는 이것을 메타에 대해 토론하게되어 기쁘다.

3
이와 같은 소리는 프로그래머에게 질문이되었을 것입니다. 우리는 아이디어가 아니라 코드를 검토합니다.
말라기

2

첫 번째 답변에는 거기에있을 필요가없는 성능 저하가 있습니다.

try
{
    if (GetDataFromServer())
    {
        return ProcessData();
    }
    else
    {
        throw new Exception();
    }
catch(Exception ex)
{
    return null;
}

예를 들어 if 문을 종료하여 Catch 문에 들어가면 코드 전환 방향을 지정할 필요가 없습니다.

return null; else 문에서 throw 된 후 catch되는 catch가 아닌 else 문에서이 작업 을 수행 하려는 경우

아마도 실제 코드 에는 적용되지 않지만 제공 한 일반 코드에는 적용됩니다.

표준은 당신이 이것을해서는 안된다고 말합니다.

표준에 따르면 이렇게해야한다고 말합니다 (다시 OP에 제공된 일반 코드를 기반으로 함)

if (GetDataFromServer())
{
    return ProcessData();
}
else
{
    Return null
}

그리고 당신이 잡는 특별한 예외가 없기 때문에 여기서 시도를 잡아서는 안됩니다.

예외가 발생한 경우 예외를보고 예외를 작성하는 문제를 해결할 수 있습니다.


1

왜 그렇게 간단하지 않습니까?

if (!GetDataFromServer()) return null;
ProcessData();

예외 처리기가 존재할 경우 ProcessData ()에 있어야합니다.


예외를 ProcessData()최상위 수준 으로 전달하고 싶지 않은 이유는 무엇 입니까?
grovesNL

@grovesNL 여기서는 예외로 유용한 것이 없습니다.
Loren Pechtel

1
어떻게 요? ProcessData()이제 예외가 발생 하면 처리되지 않습니다. 자체 를 수정하지 않고 예외가 발생 return null하면이 수준으로 유지 하고 싶습니다 . ProcessData()ProcessData()
grovesNL
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.