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

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

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



답변

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

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

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


답변

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

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

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


답변

코드 스 니펫이 주어지면 완전히 무의미 해 보입니다. 나에게 초기 코드 패턴은 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가 참조로 전달되도록 보장하기 위해 사용하기 전에 누군가 사용한 방법 일 것입니다.


답변

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


답변

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

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