web-dev-qa-db-ja.com

bool / intを返し、実際のオブジェクトを出力パラメーターとして持つメソッドがあるのはなぜですか?

会社のコードベース(.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
}

使用しない値を返す代わりに、FooメソッドがIDを取得してBazオブジェクトを返すのではなく、なぜこれを行うのかについて頭を悩ませています実際のオブジェクトを参照または出力パラメーターにする。

私が見逃しているこのコーディングスタイルの隠された利点はありますか?

12
Wayne Molina

通常はこのパターンを使用するため、次のようなコードを記述できます。

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

これは、たとえば、辞書クラスのTryGetValueのCLRで使用されます。それはいくつかの冗長性を回避しますが、outおよびrefパラメーターは常に私には少し厄介に見えました

11
Homde

これは、例外が発生する前の古いCスタイルのコードです。戻り値は、メソッドが成功したかどうかを示し、成功した場合、パラメーターは結果で満たされます。

.netでは、そのための例外があります。このパターンに従う必要はありません。

[編集]例外処理には明らかにパフォーマンスへの影響があります。多分それはそれと関係があります。ただし、そのコードスニペットでは、既に例外がスローされています。それがより適切な場所に捕まるまでスタックを上に移動させるだけの方がクリーンです。

11
Sean Edwards

コードスニペットを考えると、完全に無意味に見えます。私にとって、最初のコードパターンは、BazObjectのnullは許容可能なケースであり、boolの戻りは、失敗したケースを安全に判断するための指標であることを示唆しています。次のコードの場合:

// 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が渡されることを保証するために使用する前の誰かの方法です。

2
Joel Etherton

場合によっては、このパターンは、呼び出し元であるユーザーが、戻り値の型が参照型か値型かを気にする必要がない場合に役立ちます。このようなメソッドを呼び出して値の型を取得する場合、その値の型には確立された無効な値(double.NaNなど)が必要か、成功を判断する別の方法が必要です。

1
Kevin Hsu

アイデアは、プロセスが成功したかどうかを示す値を返すことで、次のようなコードを許可します。

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!");
}

オブジェクトcanがnullの場合、例外が発生します。

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

これはCで使用される一般的なパターンで、例外はありません。これにより、関数はエラー条件を返すことができます。例外は、一般的にはるかにクリーンなソリューションです。

0
Michael K