c#错误CS0165:使用未赋值的局部变量-忽略逻辑和out引用

本文关键字:局部变量 逻辑和 引用 out 赋值 CS0165 错误 | 更新日期: 2023-09-27 18:12:39

经过搜索,我似乎找不到为什么c#编译器抱怨局部变量dteDest

行中未赋值
if (dteSrc == dteDest) {

如果我替换

行,错误就会消失
DateTime dteSrc, dteDest;

DateTime dteSrc, dteDest = DateTime.MinValue;

据我所知,如果dteDest没有被DateTime初始化,代码将永远不会到达比较行。TryParse,它是输出参数。

我的逻辑是:

  1. 如果currentDataObj为空,则booHaveOrigDate为假,如果失败,则第一个
  2. 如果currentDataObj不为空,但不能转换为日期时间,则booHaveOrigDate为假,如果失败
  3. DateTime。如果TryParse不能转换为DateTime this和&&表示永远不会使用dteDest。

简单示例代码

void StrangeLogic(object srcData, object currentDataObj) {
   DateTime dteSrc, dteDest;
   bool booHaveNewDate = DateTime.TryParse(srcData.ToString(), out dteSrc);
   bool booHaveOrigDate = (currentDataObj != null) 
                          && DateTime.TryParse(currentDataObj.ToString(), out dteDest);
   if (booHaveNewDate && booHaveOrigDate) {
      if (dteSrc == dteDest) { 
          // Get a "use of unassignned local variable 'dteDest' 
          // unless dteDest = DateTime.MinValue beforehand
      }
   }
}

如果我改变

一行
bool booHaveNewDate = DateTime.TryParse(srcData.ToString(), out dteSrc);

到下面的

bool booHaveNewDate = (srcData != null) && DateTime.TryParse(srcData.ToString(), out dteSrc);

则编译器报错srcDate也没有赋值

有没有人可以指出我在正确的方向,我错过了什么-我不是指参数检查等,我关心的是为什么编译器逻辑似乎被使用一个常见的TryParse函数愚弄?

附加信息

即使展开逻辑仍然会给出相同的错误(使用未分配的局部变量)

bool booHaveOrigDate;
if (currentDataObj != null) 
   booHaveOrigDate = DateTime.TryParse(currentDataObj.ToString(), out dteDest); 
else 
   booHaveOrigDate = false;
if (booHaveOrigDate) {
    if (dteSrc == dteDest) {

似乎是编译器对null检查(currentDataObj != null)所做的任何事情都阻止了它正确地确定dteDest不会被访问,除非分配

将其更改为以下代码,没有问题(除了null对象上可能出现的.ToString())

bool booHaveOrigDate = DateTime.TryParse(currentDataObj.ToString(), out dteDest); 
if (booHaveOrigDate) {
    if (dteSrc == dteDest) {

c#错误CS0165:使用未赋值的局部变量-忽略逻辑和out引用

你的替换是不正确的,它应该是:

DateTime dteSrc = DateTime.MinValue, dteDest = DateTime.MinValue;

然而,你应该使用TryParse的返回变量,这是一个bool来查看TryParse是否工作,而不是如果你的booHaveNewDate:

DateTime dteSrc, dteDest;
if(DateTime.TryParse(srcData.ToString(), out dteSrc) && DateTime.TryParse(currentDataObj.ToString(), out dteDest))
{
  if (dteSrc == dteDest) { 
      // Do your stuff here
  }
}

现在你不需要在开头指定日期。

**您应该在使用前测试此代码,它不是生产代码,可能包含错误

编译器是正式正确的,分配给dteDest(作为out参数)是有条件的。在编译器看来,这可能不会发生。编译器不会"理解"TryParse()之后的逻辑。

下面是一个类似的情况:

int f(int x)
{
   int r;
   if (x <= 5)  r = 1;
   if (x >  5)  r = 2;
   return r;  // error: use of uninitialized var
}
另一方面,用 初始化似乎更符合逻辑
  DateTime dteSrc = default(DateTime), dteDest = default(DateTime);

是相同的值(DateTime.MinValue)。

我可能错了,但我不认为编译器在报告此错误时试图广泛剖析您的代码。我正在寻找一些资料来支持我的理论。与此同时,我的猜测是,这是一个设计决策,因为如果一个人花了几秒钟的时间才看到一个变量在初始化之前不会被使用,那么为了避免混淆,将其初始化为null可能是一个更好的编码决策。

编辑:

好吧,我做了一些环顾四周,虽然我发现一些例子的人说基本上相同的事情我找不到任何官方文件说明这一点。以下是我发现的回答:

"编译器完全有权不知道你的逻辑。"

http://www.pcreview.co.uk/forums/use-unassigned-local-variable-error-t3067479.html

"……当有控制流结构时,它不能评估情况,因为它没有执行代码,所以它不知道值是否被赋值了。"

http://bytes.com/topic/c-sharp/answers/917965-why-am-i-getting-unassigned-local-variable-errors

如果currentDataObj == null

dteDest将没有值设置

如果你将你的行改为:

bool booHaveOrigDate = DateTime.TryParse(currentDataObj != null ? currentDataObj.ToString() : string.Empty, out dteDest);

编译器逻辑似乎被使用常见的TryParse函数

愚弄了

上面的问题最容易回答的事实是,当编译器编译你的代码时,它不会看那个方法在内部做什么,它只会看签名。它知道它可以返回一个可能为真或假的布尔值,并且它知道它正在设置dteDest的值。

但这并不是你的问题。问题出在下面一行:
bool booHaveOrigDate = (currentDataObj != null) 
          && DateTime.TryParse(currentDataObj.ToString(), out dteDest);

使用&&运算符,如果第一部分为假,则不计算第二部分。这被称为短路求值,其工作原理是,如果第一部分为假,那么第二部分是什么都无关紧要——总体结果总是假的。

所以在这种情况下,dteDest从未被设置,编译器认为这是一个问题,即使你看一下逻辑,说如果没有设置,代码将永远不会运行。

一个简单的事实是,人们经常可以发现编译器之外的优化和特殊情况。听起来你好像已经意识到,你可以解决这个问题,只需在开始检查参数,然后返回,如果它是空的。