質問
たとえば、いくつかの同様の方法があります。 CalculatePoint(...)およびCalculateListOfPoints(...)。場合によっては、成功しないことがあり、呼び出し元にこれを示す必要があります。汎用リストを返すCalculateListOfPointsの場合、空のリストを返し、呼び出し元にこれをチェックするように要求できます。ただし、Pointは値型であるため、そこでnullを返すことはできません。
理想的には、メソッドが同様に「見える」ようにします。 1つの解決策は、それらを
として定義することです。public Point CalculatePoint(... out Boolean boSuccess);
public List<Point> CalculateListOfPoints(... out Boolean boSuccess);
または代わりにポイントを返すには? CalculatePointの場合、失敗を示すためにnullを返します。ただし、null不可の型にキャストし直す必要があることを意味します。
別の方法は、ブールboSuccessを返し、結果(ポイントまたはリスト)を「出力」パラメーターとして使用し、TryToCalculatePointまたは何かを呼び出すことです...
ベストプラクティスとは何ですか?
編集:フロー制御に例外を使用したくない!失敗が予想される場合があります。
解決
個人的には、TryParse()と同じアイデアを使用すると思います:outパラメーターを使用して実際の値を出力し、呼び出しが成功したかどうかを示すブール値を返す
public bool CalculatePoint(... out Point result);
私は&quot; normal&quot;の例外を使用するのが好きではありません。動作(関数が一部のエントリで機能しないことが予想される場合)。
他のヒント
なぜ失敗するのですか?呼び出し元が実行したこと(つまり、提供された引数)が原因である場合、ArgumentExceptionのスローは完全に適切です。例外を回避するTry [...]メソッドは問題ありません。
ただし、例外をスローするバージョンを提供することをお勧めします。したがって、常に適切なデータを提供することを期待する呼び出し元は、間違っている場合は適切に強力なメッセージ(例外)を受け取ります。
別の方法は、例外をスローすることです。ただし、通常は「例外的なケース」でのみ例外をスローします。
障害のケースが一般的である(例外ではない)場合、2つのオプションを既にリストしています。 編集:このような例外的でないケース(成功またはオブジェクトを返すかどうか)を処理する方法として、プロジェクトに規則がある場合があります。既存の規則がない場合、lucasbfrに同意し、成功を返すことをお勧めします(TryParse(...)の設計方法に同意します)。
障害が特定の理由によるものである場合、nullまたはboolを返してoutパラメーターを使用しても問題ないと思います。ただし、失敗に関係なくnullを返す場合は、お勧めしません。例外は豊富な情報を提供します。何が失敗したのか、返されたものがすべてnullである場合、データが間違っているため、メモリが不足している、またはその他の奇妙な動作があるかどうかをどのように確認できますか
.netでも、TryParseにはParse兄弟があり、必要に応じて例外を取得できます。
TrySomethingメソッドを提供した場合、失敗した場合に例外をスローするSomethingメソッドも提供します。それは呼び出し元次第です。
私が使用したモデルは、さまざまなクラスのTryParseメソッドでMSが使用するモデルと同じです。
元のコード:
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);
基本的に、成功/失敗を戻り値にします。
要約すると、次の2つの方法があります。
- 戻り値の型がPointなどの値型の場合、C#のNullable機能を使用してPointを返しますか? (別名Nullable)、失敗した場合でもnullを返すことができます
- 障害が発生した場合に例外をスローします。 「例外的」であるものとそうでないものに関する議論/議論全体。重要なポイントであり、APIであり、例外的な動作を決定します。
- Int32などの基本型でMicrosoftによって実装されたモデルに似たモデルを採用し、CalculatePointおよびTryCalculatePoint(int32.Parseおよびint32.TryParse)を提供し、1回のスローと1つのブール値の返却を行います。
- bool SuccessとGenericType Valueの2つのプロパティを持つメソッドからジェネリック構造体を返します。
シナリオによっては、nullを返すか、「最もクリーンな」と思われる例外をスローする組み合わせを使用する傾向があります。私にとっては、私が働いている会社の既存のコードベースに最適です。したがって、個人的なベストプラクティスはアプローチ1と2です。
ほとんどの場合、メソッドの動作とその使用法に依存します。
失敗が一般的で重大ではない場合、メソッドに成功を示すブール値を返させ、outパラメーターを使用して結果を伝えます。ハッシュ内のキーを検索し、データが使用できないときに非ブロックソケットでデータを読み取ろうとすると、これらの例はすべてそのカテゴリに分類されます。
失敗が予期しない場合、結果を直接返し、例外を伴うエラーを伝えます。ファイルを読み取り専用で開き、TCPサーバーに接続することは、良い候補です。
そして、時には両方の方法が理にかなっています...
Point.Empty を返します。構造の作成が成功したかどうかを確認するときに特別なフィールドを返すのは、.NET設計パターンです。可能な場合は、 out パラメータを避けてください。
public static readonly Point Empty
実験しているパターンは、多分を返しています。 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;
}
}
}
例外を使用することは、場合によっては悪い考えです(特にサーバーを作成する場合)。このメソッドには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;
}
両方の長所!
boolのTrySomething()は少なくとも1つのプラクティスであり、.netの解析メソッドでは問題なく動作しますが、一般的には好きではないと思います。
例外をスローすることはしばしば良いことですが、多くの通常の状況で起こると予想される状況には使用すべきではなく、それに関連するパフォーマンスコストがあります。
可能な場合はnullを返しても、ほとんどの場合は問題ありません。例外は必要ありません。
-あなたのアプローチは少し手続き的です-PointCalculatorクラスのようなものを作成するのはどうですか-コンストラクタのパラメータとして必要なデータを取得しますか?次に、その上でCalculatePointを呼び出し、プロパティ(PointとSuccessの個別のプロパティ)を介して結果にアクセスします。
@Kevinの例外は例外的なケースであるため、何かが起こると予想されるときに例外をスローすることは望ましくありません。
「失敗」に予想される何かを返す必要があります。通常、nullが返品の悪い選択肢です。
メソッドのドキュメントは、データが計算されないときに期待されることをユーザーに通知する必要があります。
一度、すべてのパブリックメソッドがtrue(正常に実行された)またはfalse(エラーが発生した)を返すフレームワーク全体を作成しました。値を返す必要がある場合は、出力パラメーターを使用しました。一般的な信念に反して、このプログラミング方法は実際に多くのコードを単純化しました。
さて、Pointを使用すると、失敗した場合にPoint.Emptyを戻り値として送り返すことができます。これで実際に行われるのは、X値とY値が0のポイントを返すことです。そのため、有効な戻り値になり得る場合はそれを避けますが、メソッドが(0,0)ポイントを返さない場合、それを使用できます。
申し訳ありませんが、Nullableタイプを思い出しただけです。ただし、オーバーヘッドがどの程度かはわかりません。