왜 bool / int를 반환하고 실제 객체를 출력 매개 변수로 사용하는 메소드가 있습니까?


12

회사 코드베이스 (.NET 3.5 응용 프로그램)에서 다음 코드 패턴이 있습니다.

bool Foo(int barID, out Baz bazObject) { 
    try { 
            // do stuff
            bazObject = someResponseObject;

            return true;
    }
    catch (Exception ex) { 
        // log error
        return false;
    }
}

// calling code
BazObject baz = new BazObject();
fooObject.Foo(barID, out baz);

if (baz != null) { 
    // do stuff with baz
}

사용하지 않는 값을 반환하고 실제 객체를 ref 또는 출력 매개 변수로 사용하는 대신 Foo메소드가 단순히 ID를 가져 와서 Baz객체를 반환하는 대신 왜이 작업을 수행 해야하는지에 대해 머리를 감싸려고합니다 .

이 코딩 스타일에 숨겨진 이점이 있습니까?



당신의 예에서, baznull및 반환 된 bool존재가 false되어 있지 상응. new BazObject()결코 null그렇게하지 않는 한, bazObject가 이전에 업데이트됩니다 Exception에 슬로우되는 Foo경우, false반환되는 baz수 없을 것입니다 null. 에 대한 사양Foo사용할 수 있다면 크게 도움이 될 것 입니다. 실제로 이것은 아마도이 코드에서 가장 심각한 문제 일 것입니다.
Steve Powell

오래 전에 기억이 흐릿하지만 예를 엉망으로 생각하고 "baz"가 null인지 아닌지 확인하고있었습니다. 어쨌든 패턴은 VB6에서와 같이 나에게 정말 고풍스러워 보였으며 개발자는 코드를 개선하기 위해 결코 귀찮게하지 않았습니다.
Wayne Molina

답변:


11

일반적으로 해당 패턴을 사용하므로 다음과 같은 코드를 작성할 수 있습니다.

if (Foo(barId, out bazObject))
{
  //DoStuff with bazobject
}

예를 들어 사전 클래스의 TryGetValue에 대한 CLR에서 사용됩니다. 그것은 중복성을 피하지만 out 및 ref 매개 변수는 항상 조금 지저분 해 보입니다


1
+1, 이것이 부울과 오브젝트를 모두 리턴하는 대신 오브젝트를 리턴하는 경향이있는 이유이지만
pdr

합의가 특정 상황을 제외하고는 상당히 구식 인 것처럼 보이지만 이유를 설명하기 때문에 이것을 대답으로 표시하려고합니다.
웨인 몰리나

이 답변은이 패턴의 사용을 정당화합니다. 그러나 그것이 코드베이스 전체에 있다면 Sean 측과 같은 나쁜 습관 일 것입니다.
Codism

11

이것은 예외가 있기 전에 오래된 C 스타일 코드입니다. 리턴 값은 메소드의 성공 여부를 표시하며, 성공한 경우 매개 변수가 결과로 채워집니다.

.net에는 그 목적에 대한 예외가 있습니다. 이 패턴을 따를 이유가 없습니다.

[edit] 예외 처리에 성능에 영향을주는 것은 명백합니다. 어쩌면 그것은 그것과 관련이 있습니다. 그러나 해당 코드 스 니펫에는 이미 예외가 발생했습니다. 스택이 더 적절한 장소에 닿을 때까지 위로 올리면 더 깔끔해집니다.


아니요, 동의 할 수 없습니다. 예상되는 조건에는 예외를 사용하지 마십시오. 예를 들어 문자열을 정수로 구문 분석하는 경우 누군가가 구문 분석 할 수없는 문자열을 전달할 수 있습니다. 이 경우 예외를 던져서는 안됩니다
pdr

그것은 내가 말한 것이 아닙니다. OP가 게시 한 코드를 읽으면 예외 상황이 발생하지만 메서드는이를 발견하여 대신 false를 반환합니다. 이 질문은 예상되는 조건이 아니라 오류 처리와 관련이 있습니다.
Sean Edwards

예, 주로 데이터베이스에서 데이터를로드하는 메소드에서 주로 사용되는 것 같습니다. if (baz.Select())그러나 종종 반환 값을 버리지 않고 null 또는 일부 속성에 대해 값을 확인합니다.
웨인 몰리나

@Sean, 당신이 말하는 것을 보아라. 나는 단지 ".NET에는 그 목적에 대한 예외가있다"라는 문구에 반대한다. 예외는 저에게 완전히 다른 목적을 제공합니다
pdr

1
알았어 유효하지 않은 인수의 코딩 오류를 설명하기 위해 모든 메소드에 부울을 추가해서는 안됩니다. 그러나 메소드 입력이 개발자가 아닌 사용자로부터 오는 경우 입력이 잘못되었을 경우 예외를 처리하지 않고 입력을 처리 할 수 ​​있어야합니다.
pdr

2

코드 스 니펫이 주어지면 완전히 무의미 해 보입니다. 나에게 초기 코드 패턴은 BazObject의 null이 허용되는 경우이고 bool return은 실패 사례를 안전하게 결정하는 척도라고 제안합니다. 다음 코드가있는 경우 :

// calling code
BazObject baz = new BazObject();
bool result = fooObject.Foo(barID, out baz);

if (result) { 
    // do stuff with baz
    // where baz may be 
    // null without a 
    // thrown exception
}

이렇게하면 이렇게하는 것이 더 합리적입니다. 아마도 이것은 개체 매개 변수가 C #에서 실제로 작동하는 방식을 이해하지 않고 baz가 참조로 전달되도록 보장하기 위해 사용하기 전에 누군가 사용한 방법 일 것입니다.


팀의 현재 멤버가 작성한 것 같습니다. 아마도 그것은 O_O에 대해 걱정해야 할 것입니다.
Wayne Molina

@Wayne M : 잠재적 인 훈련 기회보다 걱정이 적습니다 :)
Joel Etherton

1

이 패턴은 호출자가 반환 된 형식이 참조 형식인지 값 형식인지 신경 쓰지 않을 때 유용합니다. 값 유형을 검색하기 위해 이러한 메소드를 호출하는 경우 해당 값 유형은 유효하지 않은 값 (예 : double.NaN)이 필요하거나 성공을 결정하는 다른 방법이 필요합니다.


말이 되네요 조금 이상해 보이지만 그 이유는 타당한 것 같습니다.
Wayne Molina

0

아이디어는 프로세스가 성공했는지 여부를 나타내는 값을 반환하여 다음과 같은 코드를 허용하는 것입니다.

Baz b;
if (fooObject.foo(id, out b)) {
   // do something with b
}
else {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

객체가 null 일 수 없으면 (예제에서 올바르게 나타남) 다음과 같이하는 것이 좋습니다.

Baz b = fooObject.foo(id);
if (b != null) {
   // do something with b
}
else {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

객체 가 null 일 있는 경우 예외는 다음과 같습니다.

try {
   Baz b = fooObject.foo(id);
}
catch (BazException e) {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

예외가없는 C에서 사용되는 일반적인 패턴입니다. 함수가 오류 조건을 리턴 할 수 있습니다. 예외는 일반적으로 훨씬 깨끗한 솔루션입니다.


특히 코드에서 이미 예외가 발생했기 때문입니다.
David Thornley
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.