【问题标题】:"Error: Not all code paths return a value."“错误:并非所有代码路径都返回值。”
【发布时间】:2015-02-07 12:06:12
【问题描述】:

我的代码在编译时抛出了名义上的异常。我不明白为什么会发生这种情况,因为经过广泛搜索后,错误发生的原因似乎只有在没有退出返回语句的情况下存在,但我认为我的代码是完全包容的。

bool CheckExisting()
{
    Account loginAcc = new Account();

    string path = Application.StartupPath.ToString() + "\\Customers";
    int fCount = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length;
    for(int i = 0;i<fCount;i++)
    {
        String[] filePaths = Directory.GetFiles(Application.StartupPath + "\\Customers\\");
        XmlDocument xmlFile =new XmlDocument();
        xmlFile.Load(filePaths[i]);

        foreach(XmlNode node in xmlFile.SelectNodes("//Account"))
        {
            string firstName = node.SelectSingleNode("FirstName").InnerText;
            string lastName = node.SelectSingleNode("LastName").InnerText;
            string address1 = node.SelectSingleNode("Address1").InnerText;
            string address2 = node.SelectSingleNode("Address2").InnerText;
            string postCode = node.SelectSingleNode("Postcode").InnerText;
             string telePhone = node.SelectSingleNode("Telephone").InnerText;
            string mobile = node.SelectSingleNode("Mobile").InnerText;

            Account newAcc = new Account();

            newAcc.firstName = firstName;
            newAcc.lastName = lastName;
            newAcc.address1 = address1;
            newAcc.address2 = address2;
            newAcc.postCode = postCode;
            newAcc.telephone = telePhone;
            newAcc.mobile = mobile;

            loginAcc = newAcc;
        }

        if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName)
        {
            return true;
        }
        else
        {
            return false;
        }
        return false;
    }
}

【问题讨论】:

  • 如果我正确计算您的括号,您需要在您的 for 循环之外再添加一个 return。喜欢; return false; } return false; 最后。
  • 如果你修复了缩进,阅读你的代码会容易得多。
  • @SonerGönül 你会的。不能保证fCountDirectory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length 之后为 != 0。
  • 我的猜测是,您的意思是最终的 return false 超出了最外层循环的范围。
  • 很多 cmets 都是对的,而且我会提前将最后一个 return false; 放在括号中。嗬!抱歉这个愚蠢的错误,但谢谢大家!

标签: c# for-loop return return-value


【解决方案1】:

你的代码是有效的:

bool CheckExisting()
{
    // Some setup code

    for (int i = 0; i < fCount; i++)
    {
        // Code which isn't terribly relevant
        return ...;
    }
}

现在 C# 5 语言规范第 8.8.3 节讨论了 for 语句结尾的可达性:

如果以下至少一项为真,则for 语句的终点是可到达的:

  • for 语句包含退出for 语句的可达break 语句。
  • for 语句是可访问的,并且 for-condition 存在并且没有常量值 true

在这种情况下,后者是正确的,所以for 语句的结尾是可到达的……这就是方法的结尾。具有非 void 返回类型的方法的结尾永远无法到达。

请注意,即使 人类 可以检测到您永远无法到达 for 语句的末尾,情况也是如此。例如:

bool Broken()
{
    for (int i = 0; i < 5; i++)
    {
        return true;
    }
    // This is still reachable!
}

我们知道循环将始终至少执行一次,但语言规则不会 - 因此语句的结尾是可到达的,并且您会收到编译时错误。

【讨论】:

  • 检查这个作为答案,因为最深入的答案。很高兴听到 C 遵循的一些规则。最后的代码 sn-p 也很容易理解。谢谢。
  • 我不明白为什么编译器/语言只允许 true 的常量值而不是像上一个示例中那样的常量数值。很容易分析进入了循环,并且不难看出return 语句在每种情况下都可以访问。
  • @TimSchmelter:嗯……我的“不是一个语言设计师,而是一个语言标准审查者”的帽子,我怀疑它会使语言规范更多更多复杂的。 “真值的恒定值”非常简单——“由于以下规则,在初始迭代中必须评估为真的值”变得更加困难——而且永远不可能满足所有人。
  • @JonSkeet:您可以同时使用可理解且正确的公式,例如“存在 for 条件且无法在编译时评估为真”。如果有人不理解“编译时间”部分,则会提示错误。
  • @TimSchmelter:语言规范需要准确说明这意味着什么 - 否则您的代码可能会用一个编译器编译但不能用另一个编译器编译,这是一个问题。 (我们已经在几个地方有这个了,我不希望有更多。)
【解决方案2】:

如果 fCount 为 0,那么您的循环将不会执行,并且您不会遇到任何返回语句。

一些浓缩和改进的缩进清楚地表明:

    int fCount = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length;
    for(int i = 0;i<fCount;i++){

        ...

        if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName){
            return true;
        }
        else{
            return false;
        }
        return false;
    }

可能在“现实世界”中,fCount 永远不会为 0,但是编译器/运行时不会知道这一点。

【讨论】:

    【解决方案3】:

    发生这种情况是因为 在 for 循环之后您没有返回任何内容。

    当您的方法执行时,它应该返回您定义的类型。当代码执行路径进入你的 for 语句时,它很好,因为它返回了。如果代码没有进入 for 循环,那么您的代码不会返回任何内容。 这就是错误。 Run time 可能出现异常。用铅笔和纸浏览代码,看看它是如何执行的

    【讨论】:

      【解决方案4】:

      您错过了退货。这应该可以。

      bool CheckExisting()
      {
              Account loginAcc = new Account();
      
              string path = Application.StartupPath.ToString() + "\\Customers";
              int fCount = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length;
      
              for(int i = 0;i<fCount;i++)
              {
                  String[] filePaths = Directory.GetFiles(Application.StartupPath + "\\Customers\\");
                  XmlDocument xmlFile =new XmlDocument();
                  xmlFile.Load(filePaths[i]);
      
                  foreach(XmlNode node in xmlFile.SelectNodes("//Account"))
                  {
                      string firstName = node.SelectSingleNode("FirstName").InnerText;
                      string lastName = node.SelectSingleNode("LastName").InnerText;
                      string address1 = node.SelectSingleNode("Address1").InnerText;
                      string address2 = node.SelectSingleNode("Address2").InnerText;
                      string postCode = node.SelectSingleNode("Postcode").InnerText;
                      string telePhone = node.SelectSingleNode("Telephone").InnerText;
                      string mobile = node.SelectSingleNode("Mobile").InnerText;
      
                      Account newAcc = new Account();
      
                      newAcc.firstName = firstName;
                      newAcc.lastName = lastName;
                      newAcc.address1 = address1;
                      newAcc.address2 = address2;
                      newAcc.postCode = postCode;
                      newAcc.telephone = telePhone;
                      newAcc.mobile = mobile;
      
                      loginAcc = newAcc;
                  }
      
      
                  if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName)
                  {
                      return true;
                  }
                  else
                  {
                      return  false;
                  } 
              return false;       
              }
      
            return false;
          }
      

      【讨论】:

        【解决方案5】:
        bool CheckExisting(){
            Account loginAcc = new Account();
        
            string path = Application.StartupPath.ToString() + "\\Customers";
            int fCount = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories).Length;
            for(int i = 0;i<fCount;i++){
                String[] filePaths = Directory.GetFiles(Application.StartupPath + "\\Customers\\");
                XmlDocument xmlFile =new XmlDocument();
                xmlFile.Load(filePaths[i]);
        
                foreach(XmlNode node in xmlFile.SelectNodes("//Account")){
                    string firstName = node.SelectSingleNode("FirstName").InnerText;
                    string lastName = node.SelectSingleNode("LastName").InnerText;
                    string address1 = node.SelectSingleNode("Address1").InnerText;
                    string address2 = node.SelectSingleNode("Address2").InnerText;
                    string postCode = node.SelectSingleNode("Postcode").InnerText;
                    string telePhone = node.SelectSingleNode("Telephone").InnerText;
                    string mobile = node.SelectSingleNode("Mobile").InnerText;
        
                    Account newAcc = new Account();
        
                    newAcc.firstName = firstName;
                    newAcc.lastName = lastName;
                    newAcc.address1 = address1;
                    newAcc.address2 = address2;
                    newAcc.postCode = postCode;
                    newAcc.telephone = telePhone;
                    newAcc.mobile = mobile;
        
                    loginAcc = newAcc;
                }
        
        
                if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName){
                    return true;
                }
                else{
                    return false;
                }
            return false;
            }
        ??????
        }
        

        如果您没有进入 for 循环,则不会返回任何内容。 或者,如果您的“FCount”为“0”,则您不会返回任何内容。

        【讨论】:

          【解决方案6】:

          简单来说,就是在最后加上一个默认的return false。这是你的代码 sn-p:

                  if(txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName)
                  {
                      return true;
                  }
                  else
                  {
                      return false;
                  }
                  return false;
              }
                  return false;
          }
          

          想想fCount 为零或小于它的情况。

          for(int i = 0;i<fCount;i++)
          

          将跳过 for 循环。那么返回语句在哪里呢?这就是编译器抛出此错误的原因。

          【讨论】:

            【解决方案7】:

            我想你是故意的:(我在偷CodeCaster的清理版)

            bool CheckExisting()
            {
                //
                for(/**/)
                {
                    //
                    foreach(/**/)
                    {
                        //
                    }
            
                    if(/**/)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                    // return false; NOT HERE, because it's not reachable in the first place.
                }
                return false; // BUT HERE, in case fCount = 0
            }
            

            另外,你可以在最后去掉 if-else 并直接做

            return txtFirstName.Text == loginAcc.firstName && txtLastName.Text == loginAcc.lastName;
            

            ...因为这已经是一个布尔表达式。

            【讨论】:

              猜你喜欢
              • 2013-07-01
              • 2014-04-16
              • 2012-04-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-20
              • 1970-01-01
              相关资源
              最近更新 更多