【问题标题】:"Use of unassigned variable" -- work arounds?“使用未分配的变量”——变通?
【发布时间】:2011-07-06 20:17:21
【问题描述】:

现在我早就知道并习惯了 C# 中的这种行为,总的来说,我喜欢它。但有时编译器就是不够聪明。

我有一小段代码,目前我的解决方法不是什么大问题,但可能在类似情况下。

        bool gap=false;
        DateTime start; // = new DateTime();
        for (int i = 0; i < totaldays; i++)
        {
            if (gap)
            {
                if (list[i])
                {
                    var whgap = new WorkHistoryGap();
                    whgap.From = start; //unassigned variable error
                    whgap.To = dtFrom.AddDays(i);
                    return whgap;
                }
            }
            else
            {
                gap = true;
                start = dtFrom.AddDays(i);
            }
        }

我看到的问题是,如果您必须使用没有默认构造函数的不可空结构来执行此操作,该怎么办?如果start 不是一个简单的 DateTime 对象,是否有办法解决这个问题?

【问题讨论】:

  • 请注意,代码中实际上存在错误,但这并没有改变问题。 (gap 不应该仅仅通过将 gap 设置为 false 来设置为 true)
  • 您上面的日期时间不是“可空的”,那是日期时间吗? / System.Nullable。您正在做的是利用这样一个事实,您可以在使用值初始化变量之前声明一个变量,只要它在使用前被初始化。
  • 你为什么还有bool gap?只需将i 初始化为1 并将start 初始化为dtFrom.AddDays(1) 并摆脱它...
  • 无参数(“默认”)构造函数将始终存在于值类型(结构)中。
  • @minitech:伟大的思想都一样:D

标签: c# .net struct compiler-errors


【解决方案1】:

有时编译器不够聪明

您希望编译器解决的问题等同于停机问题。由于该问题已被证明计算机程序无法解决,因此我们只进行了最低限度的尝试来解决它。我们不做任何特别复杂的事情。你将不得不忍受它。

有关程序分析为何等同于停止问题的更多信息,请参阅我关于推导方法的终点是否可达的文章。这本质上与确定一个变量是否被明确赋值是同一个问题;分析非常相似。

http://blogs.msdn.com/b/ericlippert/archive/2011/02/24/never-say-never-part-two.aspx

如果您必须使用没有默认构造函数的不可空结构来执行此操作,该怎么办?

没有这样的动物。所有结构,无论是否为空,都有一个默认构造函数。

如果 start 不是一个简单的 DateTime 对象,是否有办法解决这个问题?

表达式default(T) 为您提供任何类型 T 的默认值。您总是可以说

Foo f = default(Foo);

并且有合法的任务。如果 Foo 是一个值类型,那么它会调用默认构造函数,该构造函数始终存在。如果它是一个引用类型,那么你会得到 null。

【讨论】:

    【解决方案2】:

    编译器无法知道您一定会设置DateTime,因为您的gap 变量。

    随便用

    DateTime start = DateTime.Now;
    

    并完成它。

    编辑更好的是,再看一遍你的代码,使用

    DateTime start = dtFrom;
    

    【讨论】:

      【解决方案3】:

      struct 中没有默认构造函数。试试看:

      struct MyStruct {
          public MyStruct() {
              // doesn't work
          }
      }
      

      您可以拥有静态构造函数,但不能为struct 定义默认构造函数。这就是为什么在这么多结构上都有静态方法Create,以及为什么你可以说new Point() 而不是Point.Empty

      任何struct 的“默认构造函数”总是将其所有字段初始化为其默认值。某些类型的 Empty 静态字段是为了方便。它实际上使性能差异为零,因为它们是值类型。

      【讨论】:

        【解决方案4】:

        在我看来,您的 bool gap 和 DateTime start 确实是一回事。尝试像这样重构:

        DateTime? gapStart = null ;
        for (int i = 0; i < totaldays; i++)
        {
            if ( gapStart.HasValue )
            {
                if (list[i])
                {
                    var whgap  = new WorkHistoryGap();
                    whgap.From = gapStart.Value ; //unassigned variable error
                    whgap.To   = dtFrom.AddDays(i);
                    return whgap;
                }
            }
            else
            {
                gapStart = dtFrom.AddDays(i);
            }
        }
        

        [编辑注意:请发布将...哦...实际编译的代码示例。它使它更容易。]

        [进一步编辑注意:您将 gap 设置为 true 并在第一次通过循环时设置您的 start 值。进一步重构如下:]

        DateTime gapStart = dtFrom.AddDays( 0 );
        for ( int i = 1 ; i < totaldays ; i++ )
        {
          if ( list[i] )
          {
            var whgap  = new WorkHistoryGap();
            whgap.From = gapStart.Value; //unassigned variable error
            whgap.To = dtFrom.AddDays( i );
            return whgap;
          }
        }
        

        【讨论】:

        • 对不起,我的代码实际上有一个逻辑错误。仍然需要间隙变量。我没有费心更新我的问题,因为它与问题无关
        【解决方案5】:

        您为什么要尝试解决语言的设计问题?即使编译器可以提前计算出你的整个循环,这在编译器看来是不必要的复杂,它怎么知道在你的部分代码中不能抛出异常?您必须为 start 分配一个值,因为您稍后会在代码中使用它,可能在它(根据您)不可避免的分配之前。

        【讨论】:

          猜你喜欢
          • 2014-03-07
          • 1970-01-01
          • 2016-10-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-18
          • 2015-11-09
          相关资源
          最近更新 更多