2

以下のようなコードで、.NETコンパイラがすべてのコードパスが値を返すことを確立できないのはなぜですか?

bool Test(bool param) {
    bool test = true;
    if (param)
        test = false;
    else
        test = false;
    if (!test)
        return false;
}

エラーCS0161:すべてのコードパスが値を返すわけではありません!

コードはリファクタリングできますが、コンパイラはそれを示唆していません。しかし、すべてのリターンパスがカバーされています-それでは、なぜコンパイラはそれらがカバーされていないと文句を言うのですか?

編集:ここでの結論は次のとおりだと思います:

(error CS0161) + (all code paths obviously return a value) => refactor code.  

その翻訳の習慣を身につけたら、私はすべてが大丈夫だと思います。

4

5 に答える 5

11

Visual Studio 2010に含まれているC#言語仕様4.0から。

10.6.10「メソッド本体」:

メソッドのreturn型がvoidでない場合、そのメソッドの本体の各returnステートメントは、return型に暗黙的に変換可能な式を指定する必要があります。値を返すメソッドのメソッド本体のエンドポイントに到達できないようにする必要があります。つまり、値を返すメソッドでは、メソッド本体の端から制御が流出することは許可されていません。

到達可能性の定義はここにあります(強調が追加されました):

8.1「エンドポイントと到達可能性」:

実行によってステートメントに到達できる可能性がある場合、そのステートメントは到達可能であると言われます。逆に、ステートメントが実行される可能性がない場合、そのステートメントは到達不能であると言われます。

..。

特定のステートメントまたはエンドポイントが到達可能かどうかを判断するために、コンパイラーは、各ステートメントに定義された到達可能性ルールに従ってフロー分析を実行します。フロー分析では、ステートメントの動作を制御する定数式(§7.19)の値が考慮されますが、非定数式の可能な値は考慮されません

は定数式ではないため!test(常に評価されますがtrue)、コンパイラーはフロー分析でそれを考慮しないようにする必要があります。この制限の理由の1つ(おそらく唯一の理由)は、この種のフロー分析を実行することは一般的なケースでは不可能であるということです。

エラーを取り除くには、句内またはメソッドの最後に無条件に別のreturnステートメントを含める必要があります。else

于 2012-04-11T21:41:01.923 に答える
10

Eric Lippertのブログから:

到達可能性アナライザーはあまりスマートではありません。可能な制御フローが2つしかないこと、およびそれらすべてをリターンでカバーしていることを認識していません。

(ブログ投稿はswitchステートメントに関するものですが、到達可能性アナライザーはステートメントに対してそれほど賢くないと思いifます。)

于 2012-04-11T21:33:00.077 に答える
3

これは、何が初期化され、どの行が実行されるかに関して、コンパイラがどれだけ賢いかという制限を表しているにすぎません。

私は時々これに遭遇します。しかし、それが問題になることはめったにありません。私は通常、コードを少し再構築します。

于 2012-04-11T21:31:08.497 に答える
1

コードを逆方向に分析してみましょう。

問題:コードが値を返さない。

質問:コードのどこに値が返されますか?

回答:最後の行です。

結論:そのため、コードの行(最後の行)は常に値を返す必要があります。

質問:最後の行は常に値を返しますか?

回答:いいえ、最初の行でに設定されているtest場合にのみ値を返します。falsetrue

結論:コンパイラが言うように、この関数は、を返すことになっている間は値を返しませんbool

于 2012-04-11T21:46:47.603 に答える
0

詳細に説明する代わりに、質問に直接答えさせてください。

  1. 関数の戻りタイプはBoolとして指定されているため、関数はTrueまたはfalseを返す必要があります
  2. パラメータは入力パラメータとして定義されているため、コンパイル時にその値を決定することはできません
  3. テスト変数の値はパラメータに依存し、ステップ2のように、パラメータ値はコンパイル時に決定できないため、テストの値はコンパイル時に決定できません。
  4. testの値はコンパイル時(ステップ3による)として知られていないため、 if(!test)のelse / default rootを探し始め、エラーをスローします。

ありがとう

于 2018-08-14T12:36:24.457 に答える