2012-01-15 8 views
4

私はメソッドにいくつかの戻り行があるのが好きではありません。だから私は、文字列の結果を戻り値を作成した - とすべての条件に私は結果を書き=何か...メソッドに "return"を書くのに最適な方法は何ですか?

しかし、私は「のtry-catchを」メカニズムを書くとき、私は公共の文字列の結果を設定する必要があります。なぜなら、私がtryで結果を返すと、コンパイラはエラーを出し、すべてのコードが戻り値を持っているとは限りません。もし私がresult = string.Emptyと書くと、メソッドの終わりに達すると、resharperは到達可能なコードではないと言います。ここでは例を挙げて、私の質問です。

"メソッドに" return "を書くにはどうすればよいですか?"

public static string PingThatAddress(string hostAddress) 
    { 
     try 
     { 
      Ping ping = new Ping(); 
      PingReply pingreply = ping.Send(hostAddress); 

      string result; 
      if (pingreply != null && pingreply.Status.ToString() != "TimedOut") 
      { 
       result = "Address: " + pingreply.Address + "\r" 
        + "Roundtrip Time: " + pingreply.RoundtripTime + "\r" 
        + "TTL (Time To Live): " + pingreply.Options.Ttl + "\r" 
        + "Buffer Size: " + pingreply.Buffer.Length + "\r"; 
      } 
      else 
      { 
       result = string.Empty; 
      } 

      return result; 
     } 
     catch (Exception pingError) 
     { 
      Debug.Fail(pingError.Message + " " + pingError); 
     } 
     //compiler error: THERE IS NO RETURN VALUE here? 
    } 
+9

"メソッドにはいくつかのリターンラインがあるのが好きではありません" - なぜですか?メソッドを単純化するための最良の方法の1つです。 – Oded

+0

あなたはどの例外を予期していますか?また、*その他の例外も同様に扱いますか? – hvd

+2

複数のreturn文を使用することに疑問がある場合は、[この問題についてのstackoverflow投票]を見てください(http://stackoverflow.com/questions/36707/should-a-function-have-only-one-return -statement) –

答えて

4

public static string PingThatAddress(string hostAddress) 
{ 
    string result = string.Empty; 
    try 
    { 
     Ping ping = new Ping(); 
     PingReply pingreply = ping.Send(hostAddress); 

     if (pingreply != null && pingreply.Status.ToString() != "TimedOut") 
     { 
      result = "Address: " + pingreply.Address + "\r" 
       + "Roundtrip Time: " + pingreply.RoundtripTime + "\r" 
       + "TTL (Time To Live): " + pingreply.Options.Ttl + "\r" 
       + "Buffer Size: " + pingreply.Buffer.Length + "\r"; 
     } 

    } 
    catch (Exception pingError) 
    { 
     Debug.Fail(pingError.Message + " " + pingError); 
    } 
    return result; 
} 

それからちょうどresultは、例外の場合には理にかなって何かに設定されていることを確認してください。

あなたは、このようにそれを行うには、ReSharperのはに関する警告されているものに固執しようとしている場合:

public static string PingThatAddress(string hostAddress) 
{ 
    try 
    { 
     Ping ping = new Ping(); 
     PingReply pingreply = ping.Send(hostAddress); 

     string result = string.Empty; 
     if (pingreply != null && pingreply.Status.ToString() != "TimedOut") 
     { 
      result = "Address: " + pingreply.Address + "\r" 
       + "Roundtrip Time: " + pingreply.RoundtripTime + "\r" 
       + "TTL (Time To Live): " + pingreply.Options.Ttl + "\r" 
       + "Buffer Size: " + pingreply.Buffer.Length + "\r"; 
     } 
     return result; 

    } 
    catch (Exception pingError) 
    { 
     Debug.Fail(pingError.Message + " " + pingError); 
    } 
    return string.Empty; 
} 

あなたはここに物事両方の方法を使用することはできません:複数のreturn文を持っていないあなたの人工的な標準は、おそらくです何がResharperに問題を引き起こしているのですか?

+0

ありがとうございます。しかし今、resharperは言う。 "デクリメントをより使いやすくする"。私は、スタンドアーツのコーディングでこれを行うための完璧な方法は何かについてこの質問をします。私はどんな場合でも再共有推奨を無視したくありません。 –

+0

メソッドの最後にresult = string.Emptyと書くと、resharperは到達可能なコードではないと言います。しかし、私はそれを行う最良の方法があると思います。知りません。それは最善の方法でなければなりません... –

+0

@LostInLib私は 'result = string.Empty'とは言いませんでした。私は 'return string.Empty'と言った。私の新しい答えを確認してください –

0

例外の場合、値を返さない。あなたが代わりにこのようにそれを行うことができ

+1

OPは例外をキャッチして処理しています。ここで値を返すことは適切かもしれません。 –

+0

非常にあなたの答えをありがとう。しかし、私はそれを取得しません。なぜtry-catchブロックで値を返さないでください。 –

+0

私の意見では、LostInLibはcatchブロックにreturnステートメントを書くか、コードを使用する可能性があります。あなたのコードのエンハンスメントは単一の返信文ですが。 – rekire

2

受け入れられた回答の最初の部分を含む提案や元の質問の中には、特に例外が発生した場合に誤った結果を返す可能性が高いものがあります。

この問題は数回発生しますが、単一の戻り値がある場合は、メソッドのロジックのマイナーな変更によって、元のメソッドライターが予期していないコードが必ず通過することになります戻り値の変数がメソッド内で複数回正しく設定されていないか、まったく設定されていないことになります。

呼び出し元に戻すための値を収集し、それに続くメソッドでいくつかの追加のタスクを実行する必要があるのは間違いありませんが、ルール全体ではなく例外である必要があります。

単一の戻り値を持つことを望んでいるために導入されたバグが非常に多く追跡された後、私たちの開発標準では絶対に必要でない限りreturnが使用されることが指示されています。コードとそれに続く修飾子の警告が表示されます。

この方法の利点は、メソッドのロジックを変更して、新しいコードパスが戻りロジックに「穴」を生じさせる場合、コンパイラが自動的にこれについて通知されることです。単一の戻り値を使用すると、開発者は、何も見逃していないことを検証するために、考えられるすべてのコードパスを視覚的に検査する必要があります。

最後に、例外外の戻り値を持つのではなく、適切なデフォルト値が例外ハンドラ内から返されることが必要です。このようにして、例外が発生した場合に何が起こるかについては明白です。

だから、私たちの環境の中で、あなたのコードは次のようになります。

public static string PingThatAddress(string hostAddress) 
{ 
    try 
    { 
     Ping ping = new Ping(); 
     PingReply pingreply = ping.Send(hostAddress); 

     if (pingreply != null && pingreply.Status.ToString() != "TimedOut") 
     { 
      return "Address: " + pingreply.Address + "\r" 
       + "Roundtrip Time: " + pingreply.RoundtripTime + "\r" 
       + "TTL (Time To Live): " + pingreply.Options.Ttl + "\r" 
       + "Buffer Size: " + pingreply.Buffer.Length + "\r"; 
     } 
     else 
     { 
      return string.Empty; 
     } 
    } 
    catch (Exception pingError) 
    { 
     Debug.Fail(pingError.Message + " " + pingError); 
     return string.Empty; 
    } 
} 
+0

ありがとうございました。あなたは正しいですが、私はresharperが私に推薦するものすべてをしようとします(必ずしもそうではありませんが、私は試しています)。そしてresharperはあなたのコードに言います。 "else"ブロックと "return string.Empty;" catchブロックに到達できないコードです。 - あなたの答えを役に立つものとしてクリックします。 –

+1

これは一般的なアプローチ(resharperの指示に従います)ですが、この場合はresharperにバグがあるようです。まず、リリースモードでは、Debug.Failは決して実行されないので、戻り値に達するでしょう。次に、デバッグモードでは、すべてのDebug.Failはメッセージを表示し、ユーザーが何をすべきかを決定します。提示された選択肢の少なくとも1つは、例外を無視して実行することです。この場合、リターンにも到達します。したがって、このコードのresharper解析にはバグがあります。 –

+0

"Andrew Barber"の最初の答えでは、Debug.Failはコンパイルされたアプリケーションでは実行されません(デバッグではなく、リリースモードでコンパイルされます)。しかし、プログラムはcatchブロックを終了して続行し、次のステートメント "return result;"を読み込みます(結果はstring.Emptyです)。私は正しい?そういう場合には? &何が表示されますバグですか? –

2

ですから、あなたがその出口点に到達助けているifの文(または他のプログラム・フロー計算書)が、ではないことを主張しています実際には出口ポイント自体は?その制御ステートメントとreturnステートメントの唯一の違いは、returnステートメントが実際には見やすく、読みやすく、メンテナンスが容易で、エラーが発生しにくいということです。また、return文はどのレベルでも動作するので、制御文をx回繰り返す可能性があります。

最終的にreturnステートメントを使用する唯一の理由は、リソース処理です。つまり、最初に要求したリソースを取り除くことです。これはC/C++(そしてC++でさえ、これを使わなくても厄介なことになっています)ではるかに一般的です。 Javaでは、例外メカニズムとfinallyステートメントを使用してリソースを処理する必要があります(Java 7では「リソースを試そう」機能)。

returnステートメントには他にも理由があります。コンパイラがreturn(またはそれに関してはスロー)がメソッドの終わりであることを知っているので、最終変数を挿入する方が簡単です。最終的な変数は、コードに慣れれば、コードを読みやすくなり、間違いを避けることができます。

boolean someErrorCondition = true; 
    final int setSomething; 
    for (int i = 0; i < 8; i++) { 
     if (i == 7) { 
      setSomething = 11; 
      break; 
     } 

     if (someErrorCondition) { 
      return; 
     } 
    } 

コンパイラは、最終的な変数(無効な状態になっていない、全体的なアイデアだった)に設定されていない文句を言うので、これはあなたのアプローチでは動作しません。

多くの優秀な開発者と言語設計者が複数のリターンステートメントを選んでいます。私は他の方向に向かうことに対して誰にも緊急にアドバイスするだろう。

+0

申し訳ありませんが、この例ではJavaでしたが、ドリフトが発生します –

0

複数のreturn文により、コードを簡単にフォローできます。このようにして、異なるメソッド戻り点がすぐに表示されます。反対に、「結果」フィールドを返すと、フィールドが変更された後にそのフィールドが使用される場所がわかります。メソッドの自然な流れに従うのが難しくなります。しかし、とにかく、通常、欲望はスタイルの好みに関するものです。 2つの方法を混在させないように注意してください。

関連する問題