C# 错误 CS0165:使用未分配的局部变量 - 忽略逻辑和输出引用

发布于 2024-12-12 03:34:05 字数 2153 浏览 1 评论 0原文

环顾四周后,我似乎无法找到为什么 C# 编译器抱怨行中的局部变量 dteDest 未分配

if (dteSrc == dteDest) {

错误就会消失

DateTime dteSrc, dteDest;

如果我将行替换为 ,

DateTime dteSrc, dteDest = DateTime.MinValue;

据我所知,代码将如果 dteDest 未由 DateTime.TryParse 初始化(它是其输出参数),则永远不会到达比较线。

我的逻辑是:

  1. 如果 currentDataObj 为 null,则 booHaveOrigDate 为 false,第一个 if 失败
  2. 如果 currentDataObj 不为 null 但无法转换为 DateTime,则 booHaveOrigDate 为 false,第一个 if > 失败
  3. DateTime.TryParse 如果无法将其与 && 一起转换为 DateTime,则返回 false意味着 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) {

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

将其更改为此代码,没有问题(除了空对象上可能的 .ToString()

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

After searching around I cant seem to locate why the C# compiler is complaining that the local variable dteDest is unassigned in the line

if (dteSrc == dteDest) {

The error goes away if I replace the line

DateTime dteSrc, dteDest;

with

DateTime dteSrc, dteDest = DateTime.MinValue;

As far as I can see the code will never reach the comparison line if dteDest is not initialised by the DateTime.TryParse which it is an out parameter for.

My logic is:

  1. If currentDataObj is null then booHaveOrigDate is false and the first if fails
  2. If currentDataObj is not null but cant be converted to a DateTime then booHaveOrigDate is false and the first if fails
  3. DateTime.TryParse will return false if it cant convert to a DateTime this along with the && means that dteDest will never be used.

Simple Sample Code

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
      }
   }
}

Also if I change the line

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

to the following

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

then the compiler complains that srcDate is not assigned as well.

Could anyone point me in the right direction to what I am missing - I dont mean about parameter checking etc I am concerned with why the compiler logic seems to be fooled by the use of a common TryParse function?

Additional Info

Even expanding out the logic still gives the same error (use of unassigned local variable)

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

if (booHaveOrigDate) {
    if (dteSrc == dteDest) {

It appears that it is whatever the compiler does with the null checking (currentDataObj != null) that prevents it from correctly determing the dteDest wont be accessed unless assigned

Change it to this code and no problems (aside from the possible .ToString() on a null object

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

凹づ凸ル 2024-12-19 03:34:05

您的替换不正确,应该是:

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
  }
}

现在您不必在开始时分配日期。

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

Your replace is incorrect, it should be:

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

However you should use the return variable of TryParse, which is a bool to see if tryparse worked instead if your booHaveNewDate:

DateTime dteSrc, dteDest;

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

Now you do not have to assign the dates in the beginning.

** You should test this code before using, it is no production code and can contain errors

雾里花 2024-12-19 03:34:05

编译器在形式上是正确的,对 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)进行初始化似乎更符合逻辑。

The compiler is formally correct, the assignment to dteDest (as out parameter) is conditional. In the eyes of the compiler it might not happen. The compiler doesn't 'understand' the logic that follows from TryParse().

Here is a similar situation:

int f(int x)
{
   int r;

   if (x <= 5)  r = 1;
   if (x >  5)  r = 2;

   return r;  // error: use of uninitialized var
}

On a side note, it seems slightly more logical to initialize with

  DateTime dteSrc = default(DateTime), dteDest = default(DateTime);

it is the same value (DateTime.MinValue) though.

恋你朝朝暮暮 2024-12-19 03:34:05

我可能是错的,但我不认为编译器在报告此错误时会尝试广泛剖析您的代码。我目前正在尝试寻找一些来源来支持我的理论。同时,我的猜测是,这是一个设计决策,因为如果一个人需要花费超过几秒钟的时间才能看到变量在初始化之前不会被使用,那么将其初始化为 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

I could be wrong but I don't think the compiler attempts to dissect your code that extensively when reporting this error. I'm currently trying to find some source to back up my theory. In the mean time, my guess would be that this is a design decision because if it takes a person more than a couple seconds to see that a variable will not be used before being initialized it's probably a better coding decision to just null initialize it to begin with in order to avoid confusion.

EDIT:

Well I did a bit of looking around and while I found a couple examples of people saying essentially the same thing I am I cannot find any official documentation stating this. Here are the responses I found though:

"The compiler is perfectly entitled to not know your logic."

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

"...when there's a control flow structure, it can't evaluate the situation, because it's not executing code, so it doesn't know if the values are getting assigned."

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

一张白纸 2024-12-19 03:34:05

如果 currentDataObj == nulldteDest 将不会设置值,

如果您将行更改为:

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

dteDest will not have a value set if currentDataObj == null

It will work if you change your line to:

bool booHaveOrigDate = DateTime.TryParse(currentDataObj != null ? currentDataObj.ToString() : string.Empty, out dteDest);
悍妇囚夫 2024-12-19 03:34:05

编译器逻辑似乎被通用 TryParse 函数的使用所愚弄

上面的问题可以通过以下事实最容易回答:当编译器编译代码时,它不会查看该方法是什么在内部执行时,它只查看签名。它知道它可以返回一个可能为 true 或 false 的布尔值,并且它知道它正在设置 dteDest 的值。

但这并不是你真正的问题。问题在于以下行:

bool booHaveOrigDate = (currentDataObj != null) 
          && DateTime.TryParse(currentDataObj.ToString(), out dteDest);

使用 && 运算符,如果第一部分为 false,则不会计算第二部分。这称为短路评估,其工作原理是:如果第一部分是错误的,那么第二部分是什么并不重要 - 总体结果将始终是错误的。

因此,在这种情况下,dteDest 永远不会被设置,并且编译器认为这是一个问题,即使您查看逻辑并说如果未设置,代码将永远不会运行。

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

compiler logic seems to be fooled by the use of a common TryParse function

The question above can be most easily answered by the fact that when the compiler is compiling your code it doesn't look at what that method is doing internally, it just looks at the signature. It knows it can return a boolean that may be true or false and it knows that it is setting the value of dteDest.

This isn't really your problem though. The problem comes in that the following line:

bool booHaveOrigDate = (currentDataObj != null) 
          && DateTime.TryParse(currentDataObj.ToString(), out dteDest);

Uses the && operator which will not evaluate the second part if the first part is false. This is called short circuit evaluation and works on the theory that if the first part is false then it doesn't matter what the second part is - the overall result will always be false.

So in this case dteDest is never being set and the compiler feels this is a problem, even if you look at the logic and say that the code will never run if it is not set.

The simple fact is that people can often spot optimisation and special cases that are beyond the compiler. You sound like you are already aware that you can solve this simply just by checking the parameter at the beginning and then returning if its null.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文