32

2つのメソッドbool Foo()とがありbool Bar()ます。次のうちどれがより読みやすいですか?

if(Foo())
{
    SomeProperty = Bar();
}
else
{
    SomeProperty = false;
}

また

SomeProperty = Foo() && Bar();

一方では、短絡&&は便利な機能であり、2番目のコードサンプルははるかに短いと思います。一方で、一般的に&&条件文の外を見ることに慣れているかどうかわからないので、それが最初のサンプルをより良い選択肢にする認知的不協和をもたらすのではないかと思います。

どう思いますか?決定に影響を与える他の要因はありますか?たとえば、&&式が画面に収まる1行より長い場合、前者を優先する必要がありますか?


回答後の説明:

答えが持ち出した最初の質問に含めるべきだったいくつかのこと。

  • Bar()よりも実行に費用がかかる可能性がありますFoo()が、どちらの方法にも副作用はありません。
  • この例のように、メソッドにはどちらもより適切な名前が付けられています。 Foo()要約すると、次のようなものにCurrentUserAllowedToDoX()なりBar()ます。XCanBeDone()
4

21 に答える 21

93

Foo() && Bar() 形式が合理的であるという一般的なコンセンサスに同意しますが、Bar() がその副作用とその値に役立つ場合を除きます。

Bar() がその値だけでなくその副作用にも役立つ場合、私の最初の選択は Bar() を再設計して、その副作用の生成とその値の計算が別の方法になるようにすることです。

なんらかの理由でそれが不可能な場合は、元のバージョンを大いに好む. 私にとって、元のバージョンは、Bar() への呼び出しがその副作用に役立つステートメントの一部であることをより明確に強調しています。後者の形式は、Bar() がその値に役立つことを強調しています。

たとえば、

if (NetworkAvailable())
  success = LogUserOn();
else
  success = false;

success = NetworkAvailable() && LogUserOn();

私は前者を取ります。私には、後者の重要な副作用を見落とすのはあまりにも簡単です.

ただし、どちらかを選択する場合

if (NetworkAvailable())
  tryWritingToNetworkStorage = UserHasAvailableDiskQuota();
else
  tryWritingToNetworkStorage = false;

tryWritingToNetworkStorage = NetworkAvailable() && UserHasAvailableDiskQuota();

私なら後者を選びます。

于 2009-10-09T17:04:48.627 に答える
46

あなたの言語がそれを許すと仮定して、私はこの速記法が好きです:

SomeProperty = Foo() ? Bar() : false;
于 2009-10-09T16:43:57.433 に答える
19
SomeProperty = Foo() && Bar();

これははるかに読みやすいです。率直に言って、他の人をどのように選択できるかわかりません。&& 式が 1 行より長い場合は、2 行に分割してください...

SomeProperty = 
   Foo() && Bar();

      -or-

SomeProperty = Foo() && 
               Bar();

それは読みやすさとIMHOの理解をほとんど損ないません。

于 2009-10-09T16:44:28.743 に答える
13

Foo と Bar が何をするかによります。

たとえば、IsUserLoggedIn() && IsUserAdmin()は間違いなく として優れて&&いますが、if が優れている他の組み合わせがいくつかあります (オフハンドは考えられません)。

全体的に、私はお勧めし&&ます。

于 2009-10-09T16:45:23.377 に答える
9

ない。SomeProperty、Foo、Bar の名前を変更することから始めます。

つまり、意図を明確に伝えるようにコードを構成する必要があります。機能が異なると、さまざまな形式を使用する場合があります。ただし、現状では、どちらの形式でも問題ありません。検討:

IsFather = IsParent() && IsMale();

if (FPUAvailable()) {
    SomeProperty = LengthyFPUOperation();
} else {
    SomeProperty = false;
}

ここで、最初の形式は、論理 AND 関係を強調しています。2番目のものは短絡を強調します。最初の例を 2 番目の形式で書くことは決してありません。特に明確にすることを目的としている場合は、2 番目の例では 2 番目の形式を使用することをお勧めします。

ポイントは、この質問に SomeProperty と Foo() と Bar() で答えるのは難しいということです。通常のケースで && を擁護するいくつかの優れた一般的な回答がありますが、2 番目の形式を完全に除外することはできません。

于 2009-10-09T17:43:45.397 に答える
6

人々は 2 番目のものをどのように誤解する可能性があると思いますか? && がショートサーキットであることを忘れて、最初の条件が false のときに 2 番目の条件が呼び出された場合に何が起こるかを心配すると思いますか? もしそうなら、私はそれについて心配しません - 彼らは同様に混乱するでしょう:

if (x != null && x.StartsWith("foo"))

これを最初の形式として書き直す人はあまりいないと思います。

基本的に、私は2番目に行きます。適切に説明的な変数名 (および条件) があれば、まったく問題ありません。

于 2009-10-09T16:48:08.627 に答える
5

この場合のように、条件式が短く簡潔な場合は、2番目の方がはるかに読みやすいと思います。ここで何をしようとしているのかが一目でわかります。最初の例では、何が起こっているのかを理解するために2パスかかりました。

于 2009-10-09T16:43:51.177 に答える
4

私は2番目に行きますが、おそらく最初のように書いてから、変更します:)

于 2009-10-09T16:44:10.710 に答える
3

最初のものを読んだとき、ステートメントのelse部分を読むまで、SomePropertyがブール値のプロパティであることがすぐには明らかではなく、Bar()がブール値を返すこともわかりませんでした。

私の個人的な見解は、このアプローチがベスト プラクティスである べきだというものです。コードのすべての行は、可能な限り他のコードを参照せずに、可能な限り解釈可能であるべきです。

ステートメント 1 では、ステートメントの else 部分を参照して SomeProperty と Bar() の両方が本質的にブール値であることを補間する必要があるため、2 番目のステートメントを使用します。

2 番目のコードでは、次のすべての事実が 1 行のコードですぐに明らかになります。

  • SomeProperty はブール値です。
  • Foo() と Bar() は両方とも、ブール値として解釈できる値を返します。
  • Foo() と Bar() の両方が true と解釈されない限り、SomeProperty は false に設定する必要があります。
于 2009-10-09T16:56:25.807 に答える
3

最初のものは、はるかにデバッグ可能です

于 2009-10-09T18:02:28.007 に答える
1

特定の関数呼び出しを個別にブレークポイントしたり、変数の特定の設定を特定の値に設定したりできると便利なことがよくあります。これにより、すべてのデバッガーできめ細かなブレークポイント設定が可能になる可能性が高くなります (C# の場合、これはそれほど大きな数ではありません)。

そうすれば、Foo() の呼び出しの前、Bar() (および変数のセット) の呼び出しの前、および変数が false に設定されているときに、ブレークポイントを設定できます。 Foo() 対 !Foo() のケースをトラップするために使用されます。これは、考えている質問に応じて異なります。

これは、すべてが 1 つの行にある場合は不可能ではありませんが、調査中の問題の原因を突き止めるために使用できる注意が必要です。

(C# はすばやくコンパイルされるため、通常、コードを再配置することは大きな問題にはなりませんが、注意散漫になります。)

于 2009-10-09T17:50:35.800 に答える
1

私は長いバージョンを選びます。なぜなら、それが何をするのか一目で明らかだからです。2 番目のバージョンでは、&& 演算子の短絡動作に気付くまで、数秒間停止する必要があります。これは巧妙なコードですが、読み取り可能なコードではありません。

于 2009-10-09T16:55:41.063 に答える
1

ちょっと待って。これらのステートメントは同等ではありませんね。私はそれらを数回見ましたが、同じものに評価されません。

最初のバージョンの省略形は、「and」演算子ではなく、三項演算子を使用することです。

SomeProperty = foo() ? bar: false

ただし、論理エラーは別として、短いバージョンの方が読みやすいという点で他のすべての人に同意します。

編集 - 追加

繰り返しますが、私が間違っていて、論理エラーがない場合、コードが何をしているのかが非常に明白であるため、2番目の方がはるかに読みやすくなります。

再度編集 - さらに追加:

今、私はそれを見ます。論理エラーはありません。ただし、これは、まだコーヒーを飲んでいない人にとっては、長いバージョンの方が明確であるということを意味していると思います.

于 2009-10-09T16:56:53.897 に答える
1

ご指摘のとおり、Bar() に副作用がある場合は、より明示的な方法をお勧めします。そうしないと、短絡を利用しようとしていることに気付かない人がいるかもしれません。

Bar() が自己完結型の場合、コードをより簡潔に表現する方法を使用します。

于 2009-10-09T16:58:57.797 に答える
1

最初のバージョンが次のような場合:

if (Foo() && Bar())
{
    SomeProperty = true;
}
else
{
    SomeProperty = false;
}

またはこのように:

if (Foo())
{
    if (Bar())
       SomeProperty = true;
    else
       SomeProperty = false;
}
else
{
    SomeProperty = false;
}

そうすれば、少なくとも一貫性が保たれます。この方法では、2 番目のケースよりもロジックに従うのがはるかに難しくなります。

于 2009-10-09T16:59:23.220 に答える
1

SomeProperty = Foo() && Bar()はるかに短いので、最良の方法は use だと思います。通常の .NET プログラマーなら、&& 演算子の仕組みを知っているはずです。

于 2009-10-09T16:45:51.630 に答える
0

私の考えでは、それは意図的で明確であることになります。

最初の方法は、Foo() が true を返さない限り Bar() を実行していないことを何気ない観察者に明らかにします。ショート サーキット ロジックにより、2 番目の例で Bar() が呼び出されるのを防ぐことができます (自分でそのように書くこともできます) が、最初の方法は一見するとはるかに意図的です。

于 2009-10-09T16:48:22.843 に答える
0

最初の方法は読みやすくなりますが、より多くのコード行を取得できます。2 番目の方法はより効果的です。セカンドの方がいいと思う

于 2009-10-09T19:39:38.530 に答える
0

AND 動作の短絡は、すべての言語で標準的なわけではないため、それが私のコードに不可欠である場合、暗示的に使用することには慎重になる傾向があります。

言語を 1 日に 5 回切り替えた直後にショート サーキットが表示されるとは思えません。

したがって、Foo() が false を返したときに Boo() を呼び出すべきでない場合は、防御的なプログラミング手法としてのみ、バージョン #2 を使用します。

于 2009-10-09T17:55:47.710 に答える
-1

C# を使用しているため、最初のバージョンを選択するか、三項?:演算子を使用します。この&&ような使い方は C# では一般的ではないため、誤解される可能性が高くなります。他のいくつかの言語 (Ruby が思い浮かびます) では、この&&パターンはより一般的であり、そのコンテキストでは適切だと思います。

于 2009-10-09T17:54:47.777 に答える
-3

実際のプログラミング言語の知識がない人が読める場合、コードは読み取り可能であると言うので、次のようなコード

if(Foo() == true and Bar() == true)
then
    SomeProperty = true;
else
    SomeProperty = false;

よりもはるかに読みやすい

SomeProperty = Foo() && Bar();

後者の構文に慣れていないプログラマーがコードを引き継ぐと、余分な数文字を書くのにかかる時間の 10 倍のコストがかかります。

于 2009-10-09T17:17:30.283 に答える