web-dev-qa-db-ja.com

条件式内でメソッドを呼び出す

引用されている場合(日付が記載されている場合) C#コーディング標準のリファレンスpdf ; Lance Huntから)、ステートメントが作成され、

33.条件式内でメソッドを呼び出さないでください。

.NETガイドライン( here または here )を含む他の場所では、この推奨事項を見たことがありません。 Huntのドキュメントにある他の非常に合理的なガイドラインとは異なり、この提案は私には直感的に思えません。誰かがそれを正当化することはできますか?

4
kmote

まあ、私はハントの文書を完全には読んでいませんが、彼のアドバイスは主に読みやすさについてであるようです。のようなステートメント...

if(myObject1.functionA() && myObject1.functionB())
{
  // do something
}

...短絡評価のため、およびif-lineの長さのために、誤解される特定のリスクがあります。代わりに...

bool resultOfA = myObject1.functionA();
bool resultOfB = myObject1.functionB();

if(resultOfA && resultOfB)
{
  // do something
}

...読みやすく、常に両方のfunction()を呼び出します。もちろん、明示的にwantを使用して短絡評価を利用する場合(おそらくfunctionAがfalseを返すときにfunctionBを呼び出さないため)、ハントのルールを無視したほうがよい場合があります(注:he 「回避」ではなく、「回避する」と言います)。

9
Doc Brown

副作用のある関数呼び出しも検討する必要があります(たとえば、一部のグローバル変数を変更します)。これは単なる読みやすさよりも重要な問題です。

if (funcA() && funcB()) ...

FuncBはfuncAが成功した場合にのみ呼び出されることを意図しているかもしれませんが、ここで間違いをする可能性もあります。両方の関数に副作用があり、両方を実行する必要がある場合、上記のコードには論理的な欠陥があります。これは、プログラマーがコードをタイトに保つことに意欲的すぎたために発生する可能性がありますが、以前は正しかったかもしれませんが、他の場所でいくつかの変更が行われたために、想定が無効になっています。

したがって、ブール式の中で副作用のある関数を呼び出すことは決して良い考えではありません。

5
Philipp Murry

まず、コンテキストからconditional expressionハントは、条件ステートメント内のブール式を意味します。これはフロー制御に関するセクションであり、他の目的でのブール式の使用や、三項「?:」演算子に基づく(私が呼ぶもの)条件式に関するものではありません。

ここでの根本的な意図は、フロー制御に使用される条件式の部分が、短絡評価または副作用から生じる可能性のある誤解を回避するべきであるということです。条件式で使用される値を取得するためにメソッド関数の呼び出しを回避する理由は見られません(副作用がない場合)。また、式の部分間の関係が明確であれば、短絡評価に依存しても問題はありません。目に見える。避けなければならないのは、隠れた接続と隠れた結果のリスクです。そう:

if (x.Contains(a) && x.Median() > b) {} // ok
if (x.Insert(a) && x.Median() > b) {} // NOT ok

さらに考慮事項があります。メソッドの呼び出しにはパフォーマンスのペナルティが伴う可能性があるため、Median()の計算が遅い場合:

if (x.Median() >= a && x.Median() <= b) {} // slower
var median = x.Median();
if (median >= a && median <= b) {} // faster

そうは言っても、ハントは彼が何を意味するのかを説明することに失敗することによって私たちに害を及ぼすと思います。うまくいけば、将来のリリースではその欠点に対処するでしょう。

4
david.pfx

複数の関数呼び出しを条件にロードし、分岐の処理を短絡評価に依存することを推奨します。

これが発生すると、プログラムのデバッグが困難になります。単一の条件内に5つの関数があり、条件が失敗したことしかわからない場合...次に、条件付きステップデバッグまたはスパムブレークポイントを実行して、実際に何が呼び出されているかを確認します。実際、その時点でリファクタリングして、各関数呼び出しを独自の行に配置する方がおそらく高速です。

最初は無害のようですが、はい、回線を節約します。ただし、このスタイルがロードされた大規模なプロジェクトで作業している場合、またはプロジェクトが成長してこのスタイルを使用している場合、デバッグ作業に時間を追加することになります。壊れるので、壊れるようにプログラムする必要があります。

3
l2affiki