13

私はいくつかの同様の方法を持っています。CalculatePoint(...) および CalculateListOfPoints(...)。場合によっては、成功しない場合があり、呼び出し元にこれを示す必要があります。一般的なリストを返す CalculateListOfPoints の場合、空のリストを返し、呼び出し元にこれを確認するように要求することができます。ただし、 Point は値型であるため、そこで null を返すことはできません。

理想的には、メソッドが「似ている」ようにしたいと思います。1つの解決策は、それらを次のように定義することです

public Point CalculatePoint(... out Boolean boSuccess);
public List<Point> CalculateListOfPoints(... out Boolean boSuccess);

または代わりにポイントを返すには?失敗を示すために null を返します。ただし、null 非許容型にキャストし直す必要があることを意味しますが、これは過剰に思えます。

もう 1 つのルートは、ブール型の boSuccess を返し、結果 (ポイントまたはリスト) を「out」パラメーターとして持ち、それらを TryToCalculatePoint などと呼ぶことです...

ベストプラクティスとは?

編集:フロー制御に例外を使用したくない! 失敗が予想されることもあります。

4

16 に答える 16

24

個人的には、 TryParse() と同じ考え方を使用すると思います: out パラメーターを使用して実際の値を出力し、呼び出しが成功したかどうかを示すブール値を返します。

public bool CalculatePoint(... out Point result);

私は「通常の」動作に例外を使用するのが好きではありません (一部のエントリで関数が機能しないことが予想される場合)。

于 2008-10-02T11:35:56.090 に答える
7

なぜ彼らは失敗するのでしょうか? 呼び出し元が行った何か (つまり、提供された引数) が原因である場合は、ArgumentException をスローすることは完全に適切です。例外を回避する Try[...] メソッドは問題ありません。

ただし、例外をスローするバージョンを提供することは良い考えだと思います。これにより、常に適切なデータを提供することを期待している呼び出し元が、間違っている場合に適切な強力なメッセージ (つまり、例外) を受け取ることができます。

于 2008-10-02T11:48:53.750 に答える
5

もう 1 つの方法は、例外をスローすることです。ただし、通常は「例外的なケース」でのみ例外をスローする必要があります。

失敗のケースが一般的である (例外的ではない) 場合は、2 つのオプションを既にリストアップしています。 EDIT : プロジェクトには、そのような例外的でないケースを処理する方法 (成功またはオブジェクトを返す必要があるかどうか) として規則がある場合があります。既存の規則がない場合は、lucasbfr に同意し、成功を返すことをお勧めします (TryParse(...) の設計方法に同意します)。

于 2008-10-02T11:36:15.637 に答える
2

失敗が特定の理由によるものである場合は、null または bool を返し、out パラメーターを使用しても問題ないと思います。ただし、失敗に関係なく null を返す場合は、お勧めしません。例外は、何かが失敗した理由を含む豊富な情報セットを提供します。返されたのが null だけの場合、データが間違っているか、メモリが不足しているか、その他の奇妙な動作が原因であるかをどのように知ることができますか。

.net でも、TryParse には Parse ブラザーがあるため、必要に応じて例外を取得できます。

TrySomething メソッドを提供する場合、失敗した場合に例外をスローする Something メソッドも提供します。あとは呼び出し元次第。

于 2008-10-02T11:50:35.073 に答える
1

Point.Emptyを返します。構造体の作成が成功したかどうかを確認したい場合に特別なフィールドを返すのは、.NET の設計パターンです。可能な場合はoutパラメータを避けてください。

public static readonly Point Empty
于 2008-10-02T13:06:15.670 に答える
1

私が使用したモデルは、MS がさまざまなクラスの TryParse メソッドで使用するものと同じです。

元のコード:
public Point CalculatePoint(... out Boolean boSuccess);
public List CalculateListOfPoints(... out Boolean boSuccess);

public bool CalculatePoint(... out (または ref) Point CalculatedValue); になります。
public bool CalculateListOfPoints(... out (または ref) List CalculatedValues);

基本的に成功/失敗を戻り値にします。

于 2008-10-02T11:40:21.197 に答える
1

要約すると、いくつかの方法があります。

  1. 戻り値の型が Point のような値型の場合、C# の Nullable 機能を使用して Point を返しますか? (別名Nullable)、そのようにして、失敗時にnullを返すことができます
  2. 失敗したときに例外をスローします。何が「例外的」で何がそうでないかに関する議論/議論全体は論点です。それはあなたのAPIであり、何が例外的な動作であるかを決定します。
  3. Int32 のような基本型で Microsoft によって実装されたモデルと同様のモデルを採用し、CalculatePoint と TryCalculatePoint (int32.Parse と int32.TryParse) を提供し、1 つのスローと 1 つの戻り値を bool にします。
  4. メソッドから、bool Success と GenericType Value の 2 つのプロパティを持つ汎用構造体を返します。

シナリオに応じて、null を返すか、例外をスローすることを組み合わせて使用​​する傾向があります。これは、私にとって「最もクリーン」であり、私が働いている会社の既存のコードベースに最も適しているように見えるためです。したがって、私の個人的なベスト プラクティスは、アプローチ 1 と 2 です。

于 2008-10-02T11:47:04.037 に答える
1

それは主に、メソッドの動作とその使用法に依存します。

失敗が一般的で重大ではない場合は、メソッドが成功を示すブール値を返し、out パラメーターを使用して結果を伝えるようにします。ハッシュでキーを検索し、利用可能なデータがない場合にノンブロッキング ソケットでデータを読み取ろうとする、これらの例はすべてそのカテゴリに分類されます。

失敗が予期しないものである場合は、結果を直接返し、例外とともにエラーを伝えます。ファイルを読み取り専用で開いたり、TCP サーバーに接続したりすることは、良い候補です。

そして時には両方の方法が理にかなっています...

于 2008-10-02T11:47:35.253 に答える
1

私が実験しているパターンは、Maybeを返すことです。これにはTryParseパターンのセマンティクスがありますが、null-return-on-error パターンと同様の署名があります。

私はまだどちらかの方法で納得していませんが、あなたの集合的な検討のためにそれを提供します. メソッドの呼び出しサイトで out パラメータを保持するために、メソッド呼び出しの前に変数を定義する必要がないという利点があります。エラーの理由を示すために、 ErrorsまたはMessagesコレクションで拡張することもできます。

Maybe クラスは次のようになります。

/// <summary>
/// Represents the return value from an operation that might fail
/// </summary>
/// <typeparam name="T"></typeparam>
public struct Maybe<T>
{
    T _value;
    bool _hasValue;


    public Maybe(T value)
    {
        _value = value;
        _hasValue = true;
    }

    public Maybe()
    {
        _hasValue = false;
        _value = default(T);
    }


    public bool Success
    {
        get { return _hasValue; }
    }


    public T Value
    {
        get 
            { // could throw an exception if _hasValue is false
              return _value; 
            }
    }
}
于 2008-10-02T13:23:14.023 に答える
0

Point では、失敗した場合に戻り値として Point.Empty を返すことができます。これで実際に行うことは、X と Y の値が 0 のポイントを返すことだけです。そのため、それが有効な戻り値である可能性がある場合は、それを避けたいと思いますが、メソッドが (0,0) ポイントを返さない場合は、 、それを使用できます。

于 2008-10-02T12:32:34.363 に答える
0

以前、すべてのパブリック メソッドが true (正常に実行された) または false (エラーが発生した) を返すフレームワーク全体を作成しました。値を返す必要がある場合は、出力パラメーターを使用しました。一般に信じられていることとは反対に、このプログラミング方法により、実際には多くのコードが単純化されました。

于 2008-10-02T12:02:54.437 に答える
0

ベストプラクティスは、戻り値は成功を意味し、例外は失敗を意味すると思います。

あなたが提供した例には、障害が発生した場合に例外を使用してはならないという理由はありません。

于 2008-10-02T11:34:36.640 に答える
0

例外を使用するのは、場合によっては悪い考えです (特にサーバーを作成する場合)。このメソッドには 2 つのフレーバーが必要です。何をすべきかを示す辞書クラスも見てください。

// NB:  A bool is the return value. 
//      This makes it possible to put this beast in if statements.
public bool TryCalculatePoint(... out Point result) { }

public Point CalculatePoint(...)
{
   Point result;
   if(!TryCalculatePoint(... out result))
       throw new BogusPointException();
   return result;
}

両方の長所!

于 2008-10-02T11:39:12.340 に答える
0

bool TrySomething() は、少なくとも .net の解析メソッドでは問題なく動作するプラクティスですが、一般的には好きではないと思います。

多くの場合、例外をスローすることは良いことですが、多くの通常の状況で発生すると予想される状況では使用しないでください。また、パフォーマンス コストも伴います。

例外が必要ない場合は、ほとんどの場合、可能な場合は null を返すことで問題ありません。

しかし、あなたのアプローチは少し手続き的です - PointCalculator クラスのようなものを作成するのはどうですか - 必要なデータをコンストラクターのパラメーターとして取りますか? 次に、その上で CalculatePoint を呼び出し、プロパティ (Point と Success の個別のプロパティ) を介して結果にアクセスします。

于 2008-10-02T11:39:36.580 に答える
0

@Kevin が例外は例外的なケースのためのものであると述べたように、何かが予想されるときに例外をスローしたくありません。

「失敗」に対して予想されるものを返す必要があります。通常、null は私の選択した悪い戻り値です。

メソッドのドキュメントでは、データが計算されない場合に何が予想されるかをユーザーに通知する必要があります。

于 2008-10-02T11:41:18.263 に答える
0

申し訳ありませんが、Nullable 型を思い出しました。それを確認してください。ただし、オーバーヘッドが何であるかはよくわかりません。

于 2008-10-08T11:02:12.577 に答える