【问题标题】:Strange behaviour of switch case with boolean value具有布尔值的开关盒的奇怪行为
【发布时间】:2012-06-21 07:30:36
【问题描述】:

我的问题不是关于如何解决这个错误(我已经解决了),而是为什么这个错误带有布尔值。

我的功能是

private string NumberToString(int number, bool flag)
{
    string str;

    switch(flag)
    {
        case true: 
            str = number.ToString("00");
            break;
        case false:
            str = number.ToString("0000"); 
            break;
    }

    return str;
}

错误是Use of unassigned local variable 'str'。 Bool 只能取真或假。所以无论哪种情况,它都会填充str。那为什么会出现这个错误呢?

此外,如果与真假案例一起添加default 案例,则此错误消失了,但是除了真假之外,布尔值还能保持什么?

为什么布尔变量会出现这种奇怪的行为?

【问题讨论】:

  • 我认为编译器在检查 switch 语句中的明确赋值时不会考虑类型的可能值。换句话说,如果 flagint 并且您有 4,294,967,296 个 case 语句,范围从 -2,147,483,6482,147,483,647,您将得到相同的错误。
  • 可能是null 我猜是bool? flag = null;
  • 之前问过同样的问题,现在寻找重复。
  • 这是运行时错误还是编译错误或警告?试试字符串 str = "";
  • 我猜编译器根本不够聪明,无法识别您在 select 语句中包含所有可能值的情况。使用 'string str = "";' 初始化 str应该有帮助。

标签: c# .net boolean switch-statement


【解决方案1】:
private string NumberToString(int number, bool flag)
{
    string str = "";

    switch(flag)
    {
        case true: 
            str = number.ToString("00");
            break;
        case false:
            str = number.ToString("0000"); 
            break;
    }

    return str;
}

写这个 string str = ""; - 你应该赋值

如果您添加默认案例,则没有机会在没有分配的情况下通过切换案例。现在是

【讨论】:

    【解决方案2】:

    我想,你想问,为什么 str 变量是未赋值的,因为 switch 语句的 case 会为其分配一些值,但编译器无法确定它是否会落在任何 case 语句中,那这就是为什么您在返回 str 时收到此错误。

    如果你添加一个带有字符串赋值的默认情况,那么编译器肯定会知道,str 会保存一些值,这就是你不会得到错误的原因

    【讨论】:

    • 但是 bool 总是持有一个值,因为它是值类型。
    • 是的,但是C#编译器没有考虑到这一点,我正在努力寻找官方来源,一找到就会发布
    • 我认为 Tim Schmelter 刚刚发布了它。 stackoverflow.com/a/8933935/284240
    【解决方案3】:

    在布尔变量上编写 switch 语句对我来说似乎有点浪费。为什么不使用条件运算符(?:):

    private string NumberToString(int number, bool flag)
    {
        return flag ? number.ToString("00") : number.ToString("0000"); 
    }
    

    代码看起来更简洁一些,不需要局部变量。

    但回到你关于为什么你的代码不能编译的问题 => 这是因为必须始终分配变量,并且这种分配不应该发生在条件语句中。

    【讨论】:

    • 你说赋值不应该发生在条件语句中。正确的?错误的。添加默认case条件语句,不会报错。
    • 是的,添加默认 case 语句确实可以修复错误。但正如我所说,用 true、false 和 default 案例编写 switch 语句似乎绝对是疯狂的,并且是 thedailywtf.com 的一个很好的候选者:-)
    • @NikhilAgrawal:这是为了让编译器尽可能简单,同时防止程序员出现简单的错误。因此,如果您表明您已经考虑过一点(默认情况),编译器会允许它。
    • 如果switch case里面有更多的代码行怎么办?您提供的是替代方案,而不是原因的解释。
    • 或者更好:return number.ToString(flag ? "00" : "0000") :)
    【解决方案4】:

    您得到的错误是关于string 变量和不是 boolean 可能的值。

    没有办法cases 没有人运行,这是真的(在这种情况下),但编译器在分析代码方面并没有走这么远。它只是查看在某些情况下未分配和使用的变量,并且没有默认变量,因此 假设 可能 在某些情况下它仍然未分配。

    【讨论】:

      【解决方案5】:

      嗯,这个问题的原因有很好的解释,但是还有一个解决问题的方法,没有提到。只需输入default 而不是第二个case

          private string NumberToString(int number, bool flag)
          {
              string str;
      
              switch (flag)
              {
                  case true:
                      str = number.ToString("00");
                      break;
                  default:
                      str = number.ToString("0000");
                      break;
              }
      
              return str;
          }
      

      它让编译器不再考虑flag 变量值,因为我们总是在switch 语句中分配default 值。

      同时考虑 if-else 语句等效解决方案:

          private string NumberToString(int number, bool flag)
          {
              string str;
      
              if (flag)
                  str = number.ToString("00");
              else
                  str = number.ToString("0000");
      
              return str;
          }
      

      我不是特别喜欢“单线”(单线解决方案),因为它们缺乏可扩展性和可读性,但最后只能使用这样的三元运算符:

          private string NumberToString(int number, bool flag)
          {
              return flag ? number.ToString("00") : number.ToString("0000");
          }
      

      当我这样做时 - 考虑使用扩展方法 + 默认布尔值为 false,例如:

      public static class intExtensions
      {
          public static string NumberToString(this int number, bool flag = false)
          {
              return flag ? number.ToString("00") : number.ToString("0000");
          }
      }
      

      然后在主类中:

              int intVal = 56;
              string strVal1 = intVal.NumberToString(true);
              string strVal2 = intVal.NumberToString();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-15
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 2012-12-01
        • 2014-06-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多