一位老同事曾经引用他的父亲谈论工具,“你必须比它聪明。”
在下面的代码中,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;
答案 0 :(得分:53)
您接受的答案显示了应该正在做什么,但没有解释为什么 Resharper首先抱怨。由于这种解释对于发现问题的其他人有用,因此它是:
你应遵循Resharper的建议并将第一行更改为:
DateTime dt;
这声明变量dt
但不为其分配任何值。这里不需要分配值,因为out
keyword会在下一行明确分配值。来自文档:
虽然作为
out
参数传递的变量在传递之前不必初始化,但在方法返回之前需要调用方法来指定值。
强调我的。分配值DateTime.Now
是不必要的并且具有误导性,因为永远不会使用该值。
我对这种情况的看法是,如果if语句失败,则返回当前日期
这不是你的代码所做的。来自documentation:
结果:当此方法返回时,包含等效于s中包含的日期和时间的DateTime值,如果转换成功,则转换失败时包含或MinValue。
如果解析失败,则使用您发布的代码,dt
将包含值DateTime.MinValue
,而不包含您指定的值DateTime.Now
。
答案 1 :(得分:23)
您的预期逻辑允许三个可能的DateTime
返回值(按优先顺序排列):
substr
。您可以通过在条件成功时执行单独的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。
答案 2 :(得分:20)
这是因为你要为dt赋值,然后将其作为out param传递。如果变量作为out参数传入:
在您的情况下,您可以通过将第一行更改为:
来修复来自ReSharper消息的消息DateTime dt;
我对这种情况的看法是,如果if语句失败,那么 返回当前日期
事实并非如此。无论您传入的DateTime对象的值如何,它都将始终返回DateTime.MinValue。
来自MSDN - DateTime.TryParse(string, out DateTime):
结果
输入:System.DateTime%
当此方法返回时,[result]包含 DateTime值 相当于s中包含的日期和时间,如果转换 成功,或 MinValue如果转换失败。转换 如果s参数为null,为空字符串(“”)或不是,则失败 包含日期和时间的有效字符串表示形式。这个 参数未经初始化传递。
(强调补充)
答案 3 :(得分:8)
out
参数始终为其分配值。始终保证被调用函数在返回之前为其赋值。因此,它将覆盖最初分配的值。
答案 4 :(得分:7)
这里的要点是关于使用out parameter modifier:
无论如何,虽然作为out参数传递的变量在传递之前不必初始化,但是在方法返回之前需要调用方法来赋值。
DateTime.TryParse
会将默认值分配给dt
,如果无法解析substr
,则生成的dt
将具有最短日期时间的值。
答案 5 :(得分: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;
答案 6 :(得分: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;