0

switch ステートメントの結果を返す前に保存する必要がありますか? または、取得時にスイッチの値を返す必要がありますか? より良いスタイルの方法はありますか?

一時変数を使用:

      public double xMax {
      get {
           double val = 0.00f;
           switch(x_option) {
                case 0:
                     val = priMax;
                     break;
                case 1:
                     val = rfMax;
                     break;
                case 2:
                     val = pwMax;
                     break;
           }

           return val;
      }
 }

returnステートメントを使用:

 public double xMax {
      get {
           double val = 0.00f;
           switch(x_option) {
                case 0:
                     return priMax;
                case 1:
                     return rfMax;
                case 2:
                     return pwMax;
           }
      }
 }

パフォーマンスの違いやクリーンアップはありますか?

4

5 に答える 5

5

個人的には2番目の形式が好きです。returnステートメントに到達するとすぐに、完了したことがすぐにわかります。追加の変数バージョンでは、コードの残りの部分を調べて、他に何かが発生するかどうかを確認する必要があります。

単一の戻り点に関する教義は、すべての手動クリーンアップなどを確実に実行したいCでは理にかなっていますが、とにかく例外の可能性を考慮しなければならない世界では、ガベージコレクタークリーンアップの大部分をtry/finally処理し、残りを処理すると、単一の出口点を主張するとコードが非常に読みにくくなる場合が多くあります。特に、メソッドの開始時に結果を判断できる場合はそうです(たとえば、「入力文字列が空の場合、結果は常に0になります。したがって、そこに返すだけです)。

編集:明確にするために、あなたの状況では、私はそれが大きな違いを生むとは思わない。しかし、これは単一のリターンポイントが乱雑になる種類のコードです。

 public int DoSomething(string input1, string input2)
 {
     // First simple case
     if (input1 == null || input2 == null)
     {
         return -1;
     }

     // Second simple case
     int totalLength = input1.Length + input2.Length;
     if (totalLength < 10)
     {
         return totalLength;
     }

     // Imagine lots of lines here, using input1, input2 and totalLength
     // ...
     return someComplicatedResult;
 }

単一の返品ポイントでは、これは次のようになります。

 public int DoSomething(string input1, string input2)
 {
     int ret;

     // First simple case
     if (input1 == null || input2 == null)
     {

         ret = -1;
     }
     else
     {
         // Second simple case
         int totalLength = input1.Length + input2.Length;
         if (totalLength < 10)
         {
             ret = totalLength;
         }
         else
         {
             // Imagine lots of lines here, using input1, input2 and totalLength
             // ...
             ret = someComplicatedResult;
         }
     }
     return ret;
 }

私は間違いなく、2番目のフォームよりも最初のフォームを読みたいと思います。

  • ネストが多いと、一般的にコードが理解しにくくなります。どこに行かなければならないか思い出せない
  • 最初の形式では、コードをこれ以上読まなくても、基本ケースに到達すれば完了したことを明確に伝えることができます。複雑なコードの後で副作用は発生しません。戻ってきます。2番目のコードでは、何が起こっているのかを理解するために、「else」ブロックを精神的にスキップする必要があります。パスを理解するために、より多くのコードを探しています。
于 2012-09-20T20:25:22.417 に答える
2

さて、最も重要なことは、それらを混ぜないことです。

最初のフォームの動機の 1 つは、getter からの単一の出口ポイントがあることです。コードが例よりも複雑である場合、それは役立つ可能性がありますが、このような単純な例では、実際には問題になりません。

コードが例のように単純である限り、2 番目の形式の単純さは適切な議論です。


コードが何も返さずにプロパティの最後に到達する可能性があるため、2 番目の例はそのままではコンパイルされません。最初のケースでは、スイッチの前に変数をデフォルト値に設定できます。2 番目のケースでは、スイッチでデフォルト オプションを使用する必要があり、変数はまったく必要ありません。

public double xMax {
  get {
    switch(x_option) {
      case 0:
        return priMax;
      case 1:
        return rfMax;
      case 2:
        return pwMax;
      default:
        return 0d;
    }
  }
}
于 2012-09-20T20:52:18.530 に答える
1

それは好みの問題ですが、私は可能な限り単一のリターンポイントを持つことを好みます。デバッグが簡単で、コードコントラクトをより明確に使用するときに事前と事後を確認できます。

于 2012-09-20T20:23:44.867 に答える
0

この質問は 2 世代前のものです。しかし、この質問は私も悩まされていたので、答えます。


ここにあなたが見ているものがあります: Syntax ASyntax B .

何を確認する必要がありますか:コード全体の構文の一貫性。

1 つのスタイルを選択し、それに固執します。これは、個人の選択、チームの選択、上司の選択などによって決定されます。ボトルネックが発生するまでパフォーマンスを気にすることは、馬よりもカートを置いていることです。


コードと複雑さの蓄積の一般的な結果として、switch ステートメントに直面した場合、誰かがどこかに悪いコードを書き、コードの 1 つのヤーン ボールで多くのことを処理しようとしました。

適切な例: 配列内の 5 つの異なる値を返す JSON を返す API 呼び出しで、それをどのように処理するか、または必要に応じてどのデータを選択するかを理解する必要があります。


ほとんどの場合、複数の return または if が発生する可能性がある場合は、すぐにコードを小さなチャンクに分割する必要があります。

たとえば、Jon Skeet のコードを見てみましょう。

public int DoSomething(string input1, string input2)
 {
     int ret;

     // First simple case
     if (input1 == null || input2 == null)
     {

         ret = -1;
     }
     else
     {
         // Second simple case
         int totalLength = input1.Length + input2.Length;
         if (totalLength < 10)
         {
             ret = totalLength;
         }
         else
         {
             // Imagine lots of lines here, using input1, input2 and totalLength
             // ...
             ret = someComplicatedResult;
         }
     }
     return ret;
 }


まず、コードをもう少し読みやすくできるかどうか見てみましょう。

private int someComplicatedTask(string input1, string input2){
    // Second simple case
    int ret = 0;
    int totalLength = input1.Length + input2.Length;
    if (totalLength < 10)
    {
        ret = totalLength;
    }
    else
    {
       // Imagine lots of lines here, using input1, input2 and totalLength
       // ...
       ret = someComplicatedResult;
    }
    return ret;
}

public int DoSomething(string input1, string input2)
 {
     return input1 == null || input2 == null ? -1 : someComplecatedTask(...);
 }

これは、「入力が null になる可能性があるのに、なぜ DoSomething を呼び出したのか?」と疑問に思うはずです。

問題がまだ解決されていないことに注意してください。私が達成したのは、コードの見栄えを良くすることだけです。

if 条件に関しては、次のように対処します。

null 入力の条件は、サニタイズ機能に移動されます。または、入力が null でない場合にのみ呼び出しが行われます。

...
if(input1 != null && input2 != null){
    output = DoSomething(input1, input2);
}
...

public int DoSomething(string input1, string input2)
{
    int len = input1.Length + input2.Length;
    return len < 10 ? len : someComplecatedTask(input1, input2);
}

private int someComplicatedTask(string input1, string input2){
    // Imagine lots of lines here, using input1, input2
    // ...
    return someComplicatedResult;
}

そのため、コードはより扱いやすくなりました。コードが歩ける経路は 2 つしかなく、すべて問題ありません。


それでは、最初のコード スニペットを見てみましょう。

public double xMax {
      get {
           double val = 0.00f;
           switch(x_option) {
                case 0:
                     val = priMax;
                     break;
                case 1:
                     val = rfMax;
                     break;
                case 2:
                     val = pwMax;
                     break;
           }

           return val;
      }
 }

私の考えでは、これは 2 つの理由で悪いこと
です。
2. Get {} は簡単です。セット {} には、適切な値を設定するための条件が含まれている必要があります。

したがって、コードは次のようになります。

public double xMax {
      set {
           double val = 0.00f;
           switch(value) {
                case 0:
                     val = priMax;
                     break;
                case 1:
                     val = rfMax;
                     break;
                case 2:
                     val = pwMax;
                     break;
           }
           xmax = value * val; // say // This makes break better in switch.
      }
      get { return xmax; }
 }

ケースから抜け出した後、さらにいくつかの(すべてのケースに共通の)操作を実行できるため、これは戻るよりも優れています。get one に関するこの例は、設定中に値がわからないため、決定木が必要になるため、より優れています。

しかし、取得中、オブジェクトは内容を正確に認識し、要求された内容を喜んで返します。

さて、あなたの 2 番目のコード例はまったく意味をなさないはずです。何を返すかを決めるのは、オブジェクトの義務ではありません。持っているものを返す必要があります。

また、設定中はとにかく無理に戻してはいけません。

学ぶべきことがたくさん残っているので、これでいくつかの疑問が解消され、さらにいくつかの疑問が生じることを願っています。

于 2015-08-23T06:21:11.613 に答える
-1

ワルシャワの軍事工科大学での私の最初のプログラミング クラスで、Dr. Eng. Zbigniew Wesołowski は、この関数は 1 つの戻り点しか持てないと述べました。それはANSI-Cでのプログラミングの紹介でしたが、彼はまた、どの言語で開発しなければならない場合でも、それは普遍的なルールであるため、決して忘れてはならない. goto ステートメントを使用したり、関数の途中で return したり、for ループ内で iterator を変更したりしようとすると、一度でも試験に合格することはできないと述べました。

途中で戻るかどうかは、年老いたジレンマです。コードがより明確になると主張する人もいれば、洗練されていないため避けるべきであると主張する人もいます。私の経験では、複数のリターンは Java コードで最も頻繁に発生しますが、c、c++、および c# プログラマーはむしろそれを避けています。これは規則ではなく、単なる観察です。

もう 1 つの観察結果は、Java 言語がコンパクトな構文を推奨していることです。Java IDE (例: eclipse) には、多くの場合、同じ行に左中括弧を配置するようにデフォルトのフォーマッターが設定されています (単なる例です)。複数の戻り値がそのアプローチに沿っており、コードをさらにコンパクトにすることができます。

反対の Visual Studio は、開き中括弧を新しい行に唯一の文字として配置します。長いファイル、多くの空白行または単一文字行を使用して、明確で太字の構文を奨励します。あるとすればどちらが良いかわかりません。

基本的には大学の授業や自宅でC#を書いています。そして、空行のある長いファイルが好きです。

私の会社では、Java コードを書いてから、慣れたよりコンパクトなスタイルを好みます。会社では、チェックスタイルを使用して、統一されたスタイリングによって優れたコード品質を維持しています。そして長年の会社存続により、チェックスタイルには複数回の返品を一切禁止するルールがありました。

stackoverflow で、パフォーマンスに影響があるという投稿を見たことがあります。答えとして、彼はそれをチェックする簡単なベンチマークの結果を得ました。実際、大きな違いはありませんでした。

私のコーディングの練習では、むしろ複数のリターンを避けています。しかし、全体的な決定は、個人の好み、経験、習慣、信念、そしておそらく品質要件によって異なります。

于 2012-09-20T20:30:22.660 に答える