【问题标题】:Would I really want to return the minimum date?我真的想返回最短日期吗?
【发布时间】:2012-06-12 17:26:45
【问题描述】:

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

在下面的代码中,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;

【问题讨论】:

  • 在这种情况下,我建议您使用多次退货。如果将最后一行替换为 return DateTime.Now 并将 using 中间的行替换为 return dtpDlgForm.ReturnVal,则更明显。

标签: c# datetime resharper default-value


【解决方案1】:

您接受的答案显示了您应该做什么,但没有解释为什么 Resharper 首先抱怨。由于此解释可能对发现您的问题的其他人有用,因此这里是:

应该遵循 Resharper 的建议并将第一行更改为:

DateTime dt;

这声明了变量dt,但没有给它赋值。这里不需要赋值,因为out keyword肯定会在下一行赋值。来自文档:

虽然作为out参数传递的变量在被传递之前不必初始化,被调用的方法需要在方法返回之前赋值

强调我的。分配值 DateTime.Now 是不必要的,而且会产生误导,因为这个值永远不会被使用。

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

这不是您的代码所做的。来自documentation

result:当该方法返回时,如果转换成功,则包含与s中包含的日期和时间等效的DateTime值,如果转换失败,则或MinValue。

如果解析失败,则使用您发布的代码,dt 将包含值 DateTime.MinValue,而不是您分配的值 DateTime.Now

【讨论】:

  • +1 很好的解释。在这种情况下,我会很感激 ReSharper 在我身边!我现在需要检查一下我所有的 TryParse 用法...... :(
【解决方案2】:

您的预期逻辑允许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’s answer

【讨论】:

  • 谢谢;所有的答案都很棒。我将其标记为“正确的”,因为即使文件名没有确定日期,然后用户关闭“对话框”表单,提示他/她输入日期,对话框结果不是“确定”它返回“今天”而不是 12/7/1941 或任何时候。
  • 这个答案是错误的。与几乎总是的情况一样,ReSharper 是正确的。问题是,正如@JonSenchnya 回答的那样, DateTime.TryParse() 总是在返回之前设置您的 dt 变量。这是out 参数的要求。因此,您的 dt 的初始值确实永远不会被返回。
  • @RossPatterson:答案“错误”如何?它在任何情况下都会产生不良结果吗?它是否陈述了事实上不正确的东西?它是否分配了“dt [that] 的初始值确实永远不会被返回”?诚然,我没有重复很多其他答案中给出的解释,只是为了避免冗余,但提供的解决方案是完整且正确的。
  • @RossPatterson:OP 问题中的原始代码在这方面是错误的(因此首先发布问题的动机),但问题已在我的答案代码中得到解决。在解析失败的情况下,分配给dt 的值没有区别,因为它被忽略了。
  • 是的,我相信道格拉斯的代码正是 OP(我)订购的:如果选项 A 有效,我会从文件名中获取日期值。如果不是,并且选项 B 有效(提示用户输入日期),我会得到那个日期。如果这两个选项都失败了,我会得到我想要的默认值(“今天”),而不是我不想要的 DateTime 最小值。
【解决方案3】:

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

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

在您的情况下,您可以通过将第一行更改为来修复 ReSharper 消息中的消息:

DateTime dt;

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

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

来自MSDN - DateTime.TryParse(string, out DateTime)

结果

类型:System.DateTime%

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

(已添加重点)

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      这里的重点是使用out parameter modifier

      虽然作为输出参数传递的变量在传递之前不必初始化,但被调用的方法需要在方法返回之前赋值。

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

      【讨论】:

        【解决方案6】:

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

        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;
        

        【讨论】:

          【解决方案7】:
          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;
          

          【讨论】:

          • 我认为如果 TryParse 成功,您的代码将在今天返回。不对,如果 TryParse 成功,应该返回解析后的值。
          • 天哪,你完全正确。更改了我的答案以反映这一点。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-21
          • 2020-06-27
          • 2011-10-02
          • 1970-01-01
          • 2019-05-18
          相关资源
          最近更新 更多