21

一位老同事曾经引用他父亲关于工具的话说,“你必须比它更聪明。”

在下面的代码中,Resharper 告诉我,“分配的值不用于任何执行路径”(指向第一行)。如果我接受它的帮助,则不会为 dt 分配值(“今天”)。

这是“我必须比它更聪明”并忽略他们的警告的情况,还是工具比我更聪明的情况,而我只是不理解它?

我对这种情况的看法是,如果 if 语句失败,则返回当前日期(我想要的默认值),但如果我默认 Resharper 的“要求”,它将返回 Datetime 的默认值,即最小日期,我假设是 7/4/1776 或 1/1/0000 左右。

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.MinValue而不是DateTime.Now您分配的值。

于 2012-06-08T16:17:22.140 回答
23

您的预期逻辑允许三个可能的返回值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;

编辑:有关为什么不应将值分配给将用作out参数的变量的解释,请参阅Mark Byers 的答案

于 2012-06-08T16:19:30.867 回答
20

这是因为您正在为 dt 分配一个值,然后将其作为out param传递。如果变量作为输出参数传入:

  • 必须先在该函数内分配一个值,然后才能在其中使用
  • 必须在该函数返回之前为其赋值

在您的情况下,您可以通过将第一行更改为:

DateTime dt;

我对这种情况的看法是,如果 if 语句失败,则返回当前日期

这不是真的。无论您传入的 DateTime 对象的值如何,它都将始终返回DateTime.MinValue 。

MSDN - DateTime.TryParse(string, out DateTime)

结果

类型:System.DateTime%

当此方法返回时,如果转换成功,[result] 包含与 s 中包含的日期和时间等效的 DateTime 值,如果转换失败,则包含MinValue。如果 s 参数为空、为空字符串 ("") 或不包含日期和时间的有效字符串表示形式,则转换失败。此参数未初始化传递。

(重点补充)

于 2012-06-08T16:19:21.813 回答
8

out参数始终具有分配给它的值。始终保证被调用函数在返回之前为其分配一个值。因此,无论如何它都会覆盖最初分配的值。

于 2012-06-08T16:19:59.397 回答
7

这里的重点是使用out 参数修饰符

尽管作为输出参数传递的变量在传递之前不必初始化,但被调用的方法需要在方法返回之前分配一个值。

DateTime.TryParse无论如何都会分配一个默认值dt,如果它无法解析substr,则结果dt将具有最小日期时间的值。

于 2012-06-08T16:20:41.363 回答
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 回答
3

此代码将使警告消失。但我认为道格拉斯的答案更容易阅读。

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 回答