2

この質問は、この質問 (のサブセット) に似ています

この場合、ランタイム タイプを使用して、返された結果の成功と失敗を区別しています。

次のパターンをよく見かけます。

public struct Result {
    public boolean IsSuccess { get;set;}
    public string ErrorMessage {get;set;}
    public int Value {get;set;}
}
...
Result result = someObject.SomeMethod();
if (result.IsSuccess) DoSomething(result.Value);
else handleError(result.ErrorMessage);

次のほうがより自然で、意図をより明確に表現していると思います(私の意見では):

public abstract class Result { }
public sealed class Failure : Result {
    public string ErrorMessage { get; set; }
}
public sealed class Success : Result {
    public int Value { get; set; }
}
...
Result result = someObject.SomeMethod();
if (result is Success) DoSomething((result as Success).Value);
else if (result is Failure) handleError((result as Failure).ErrorMessage);

また、.Net (および他の多くの言語) は、複数の catch 句 (例外の種類によって catch ブロックが選択される) を含む try-catch ブロックでこのパターンを使用することに注意してください。

編集:このパターン (つまり、実行時の型に依存する) は、F# の識別された共用体と同じです。違いは、F# ではネイティブであり、C# では、異なる目的のための構成を使用してエミュレートされることです。

編集:最初のコードの主な問題は、「部分的に初期化されたオブジェクト」のコードの匂いだと思います。100% の場合、オブジェクトの半分だけが初期化されます。.IsSuccess が評価されると、それ以降はオブジェクトの一部のみが使用されるため、ISPにもほぼ違反しています (成功の場合は .Result のみが使用され、エラーの場合はエラー プロパティのみが使用されます)。実行型チェック ソリューションには、これらの問題はありません。

問題は、このパターンを使用する際の問題点は何ですか? 特に、保守性、可読性、テスト容易性、概念の純粋性、OOP/OOD の観点からの問題に関心があります。

4

3 に答える 3

0

2 番目の形式が間違っているというやや学術的な理由は次のようになります。

OO 言語としての C# は、クラスは基礎となるシステムのカテゴリ(ビジネス コンセプトなど) をモデル化するために使用され、インスタンスは事実をモデル化するために使用されるという前提で設計されています。

クラスを使用して事実をモデル化することは、ツールの誤用です。

実際の影響がどうなるかはまだわかりませんが。

于 2013-09-10T16:43:19.597 に答える
0

オブジェクト指向設計は、使い捨ての情報では重要ではありません。この結果オブジェクトの寿命は非常に限られているため、スタック上の構造体として属します。

メンテナンスや可読性について話したい場合は、最初はこのコードに混乱するでしょう。

エラーの拡散をオブジェクト指向にしたい場合は、純粋に例外を使用してください (ただし、これらのユースケースのパフォーマンスは少し低下します)。

于 2013-09-10T17:48:30.087 に答える