왜 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객체를 반환하는 대신 왜이 작업을 수행 해야하는지에 대해 머리를 감싸려고합니다 .

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



당신의 예에서, baz인 null및 반환 된 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.