21

昔の職場の同僚は、父親が道具について「それよりも賢くならなければならない」と言っていた。

以下のコードでは、Resharper が「割り当てられた値はどの実行パスでも使用されていません」(最初の行を指しています) と言っています。助けの申し出を受け入れると、dt には値 (「今日」) が割り当てられません。

これは、「私はそれよりも賢くなければならない」という警告を無視するケースですか、それともツールが私よりも賢いのに、私がそれを理解していないだけのケースですか?

私の状況に対する見方は、if ステートメントが失敗した場合、現在の日付 (私が望むデフォルト値) が返されるということですが、Resharper の「要求」に同意すると、Datetime のデフォルト値が返されます。これは、1776 年 7 月 4 日または 0000 年 1 月 1 日くらいのようなものだと思います。

DateTime dt = DateTime.Now;
if (!(DateTime.TryParse(substr, out dt))) {
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) {
        if (dtpDlgForm.ShowDialog() == DialogResult.OK) {
            dt = dtpDlgForm.ReturnVal;
        } 
    }
}
return dt;
4

7 に答える 7

53

あなたが受け入れた答えは、何をすべきかを示していますが、そもそも Resharper が不平を言う理由を説明していません。この説明は、あなたの質問を見つけた他の人にとって役立つ可能性があるため、以下に示します。

Resharper のアドバイスに従い、最初の行を次のように変更する必要があります。

DateTime dt;

これは変数を宣言しますdtが、値を割り当てません。ここで値を割り当てる必要はありません。outキーワードによって次の行で確実に割り当てられるからです。ドキュメントから:

引数として渡される変数は、out渡す前に初期化する必要はありませんが、呼び出されたメソッドは、メソッドが戻る前に値を割り当てる必要があります

鉱山を強調します。DateTime.Nowこの値は決して使用されないため、値を割り当てることは不必要であり、誤解を招きます。

状況に対する私の見解は、if ステートメントが失敗した場合、現在の日付が返されるということです。

それはあなたのコードが行うことではありません。ドキュメントから:

result: このメソッドが返されるときに、変換が成功した場合は s に含まれる日付と時刻に相当する DateTime 値が含まれ、変換が失敗した場合は MinValue が含まれます。

投稿したコードでは、解析が失敗した場合、割り当てた値ではなくdt値が含まれます。DateTime.MinValueDateTime.Now

于 2012-06-08T16:17:22.140 に答える
23

意図したロジックでは、次の 3 つの戻り値が可能ですDateTime(優先順)。

  1. の解析された値substr
  2. ダイアログから選択された値。
  3. 現在の日付と時刻。

このロジックreturnは、条件が成功したときに実行される別のステートメントを持つことで実装できます。

DateTime dt;
if (DateTime.TryParse(substr, out dt))
    return dt;

using (var dtpDlgForm = new ReturnDate(
    "Please select the Date that the file was created:")) 
{
    if (dtpDlgForm.ShowDialog() == DialogResult.OK)
        return dtpDlgForm.ReturnVal;
}

return DateTime.Now;

編集:パラメーターとして使用される変数に値を割り当ててはならない理由の説明については、Mark Byers の回答outを参照してください。

于 2012-06-08T16:19:30.867 に答える
20

これは、値を dt に割り当ててから、 out paramとして渡しているためです。変数が出力パラメーターとして渡される場合:

  • その関数内で使用する前に、その関数内で値を割り当てる必要があります
  • その関数が戻る前に値を割り当てる必要があります

あなたの場合、最初の行を次のように変更することで、ReSharper メッセージからのメッセージを修正できます。

DateTime dt;

状況に対する私の見解は、if ステートメントが失敗した場合、現在の日付が返されるということです。

本当じゃない。渡す DateTime オブジェクトの値に関係なく、常にDateTime.MinValueを返します。

MSDNから- DateTime.TryParse(string, out DateTime) :

結果

タイプ: System.DateTime%

このメソッドが戻ると、[result] には、変換が成功した場合は s に含まれる日付と時刻に相当する DateTime 値が含まれ、変換が失敗した場合はMinValueが含まれます。s パラメータが null の場合、空の文字列 ("") である場合、または日付と時刻の有効な文字列表現が含まれていない場合、変換は失敗します。このパラメーターは初期化されずに渡されます。

(強調を追加)

于 2012-06-08T16:19:21.813 に答える
8

パラメータにoutは常に値が割り当てられています。呼び出された関数が戻る前に値を割り当てることが常に保証されます。したがって、どのような場合でも、最初に割り当てられた値が上書きされます。

于 2012-06-08T16:19:59.397 に答える
7

ここでのポイントは、out パラメータ修飾子の使用についてです。

out 引数として渡される変数は、渡す前に初期化する必要はありませんが、呼び出されたメソッドは、メソッドが戻る前に値を割り当てる必要があります。

DateTime.TryParseとにかくにデフォルト値を割り当て、dt解析できない場合substr、結果dtには最小日時の値が含まれます。

于 2012-06-08T16:20:41.363 に答える
3

This code would make the warning go away. But I think Douglas' answer is easier to read.

DateTime dt;
if (!(DateTime.TryParse(substr, out dt))) {
    dt = DateTime.Now;
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) {
        if (dtpDlgForm.ShowDialog() == DialogResult.OK) {
            dt = dtpDlgForm.ReturnVal;
        } 
    }
}
return dt;
于 2012-06-08T17:58:03.197 に答える
3
DateTime.TryParse(substr, out dt);

は false を返すことができますが、それでも変更されdtます。dt可能な限りいくつかの値を初期化して、その能力を最大限に発揮しようとします。C# で修飾子を使用する場合out、プログラムにそれを初期化するように指示しているので、渡した値を保持することは期待できません。

あなたができることは

DateTime dt;
if (!(DateTime.TryParse(substr, out dt))) {
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) {
        if (dtpDlgForm.ShowDialog() == DialogResult.OK) {
            dt = dtpDlgForm.ReturnVal;
        } 
        else {
            dt = DateTime.Now;
        }
    }
}

return dt;
于 2012-06-08T16:21:33.363 に答える