代码之家  ›  专栏  ›  技术社区  ›  λ Jonas Gorauskas

C:并非所有代码路径都返回值

  •  3
  • λ Jonas Gorauskas  · 技术社区  · 16 年前

    我正在编写一个简单的WinForms应用程序,允许用户在TreeView控件中拖动TreeNodes。我执行的规则之一是,不允许用户将TreeNode拖到自己的子级中。我以递归的方式编写了以下函数,以检查目标节点的父级。编译后,我得到的错误是 并非所有代码路径都返回值 对于这个函数。据我所知,我确实在这个逻辑的每个可能分支上都有一个返回语句…但我显然错了。有人能指出我的错误吗?

        private bool IsDestinationNodeAChildOfDraggingNode(TreeNode draggingNode, TreeNode destinationNode) {
            if (draggingNode.Nodes.Count == 0) 
                return false;
            else {
                if (draggingNode.Nodes.Contains(destinationNode)) 
                    return true;
                else {
                    foreach (TreeNode node in draggingNode.Nodes) 
                        return IsDestinationNodeAChildOfDraggingNode(node, destinationNode);
                }
            }
        }
    
    7 回复  |  直到 13 年前
        1
  •  8
  •   Jherico    16 年前

    实际上我认为你的算法是错误的。如果只检查第一个值,那么为什么要使用foreach语句呢?另外,返回之后的所有其他代码都是多余的,这使得代码更难执行。

    我怀疑你想做的事情更像这样:

    private bool IsDestinationNodeAChildOfDraggingNode(TreeNode draggingNode, TreeNode destinationNode) {
      // special case, no children
      if (draggingNode.Nodes.Count == 0) 
        return false;
    
      // check if the target is one of my children
      if (draggingNode.Nodes.Contains(destinationNode)) 
         return true;
    
      // recursively check each of my children to see if one of their descendants is the target
      foreach (TreeNode node in draggingNode.Nodes) 
        if (IsDestinationNodeAChildOfDraggingNode(node, destinationNode)) 
            return true;
    
      // didn't find anything
      return false;
    }
    

    有些人会坚持认为提前归还是邪恶的,这将导致这个版本的功能:

    private bool IsDestinationNodeAChildOfDraggingNode(TreeNode draggingNode, TreeNode destinationNode) {
      bool retVal = false;
    
      if (draggingNode.Nodes.Count != 0) {
    
        // check if the target is one of my children
        if (draggingNode.Nodes.Contains(destinationNode)) {
          retVal = true;
        } else {
    
          // recursively check each of my children to see if one of their descendants is the target
          foreach (TreeNode node in draggingNode.Nodes) 
            if (IsDestinationNodeAChildOfDraggingNode(node, destinationNode)) {
              retVal = true;
              break;
            }
        }
      }
    
      return retVal;
    }
    
        2
  •  13
  •   Karim    16 年前

    它可能是指这样一个事实:如果draggingnode.nodes中没有任何项,那么它将退出else,退出函数而不返回任何内容。

    也许可以这样做:

    foreach (TreeNode node in draggingNode.Nodes) 
         return IsDestinationNodeAChildOfDraggingNode(node, destinationNode);
    
    return false
    
        3
  •  2
  •   ChrisF    16 年前

    编译器认为您需要添加 return foreach 循环,因为可能没有节点 draggingNode.Nodes 所以循环实际上不会执行。

    private bool IsDestinationNodeAChildOfDraggingNode(TreeNode draggingNode, TreeNode destinationNode) {
        if (draggingNode.Nodes.Count == 0) 
            return false;
        else {
            if (draggingNode.Nodes.Contains(destinationNode)) 
                return true;
            else {
                foreach (TreeNode node in draggingNode.Nodes) 
                {
                    return IsDestinationNodeAChildOfDraggingNode(node, destinationNode);
                }
                return false; // <-- here for example
            }
        }
    }
    

    现在,这可能不是您的算法的正确位置,但是编译器认为 返回 这里失踪。按照Jherico建议的方式重新编写代码将使情况更加清楚。

        4
  •  1
  •   Ed Swangren    16 年前

    如果draggingnodes.nodes中没有项目怎么办?则不会返回值。

        5
  •  0
  •   JYelton Melchior Blausand    16 年前

    我的期望是,如果foreach中的所有元素都未能返回任何内容,或者没有节点,则foreach循环不一定返回值。在最后的if/else/foreach之后,添加一个默认返回值。

        6
  •  0
  •   John R. Strohm    16 年前

    我猜C编译器假定foreach循环正常终止,而不是返回到大约三个控制级别。

        7
  •  0
  •   Sergio Tapia    16 年前

    在外面,否则你 必须 归还一些东西。

    例如:

    private bool IsDestinationNodeAChildOfDraggingNode(TreeNode draggingNode, TreeNode destinationNode) {
    if (draggingNode.Nodes.Count == 0) 
            return false;
    else {
           if (draggingNode.Nodes.Contains(destinationNode)) 
                return true;
           else {
                foreach (TreeNode node in draggingNode.Nodes) 
                return IsDestinationNodeAChildOfDraggingNode(node, destinationNode);
                }
        }
    //Return something here.
    }
    
    推荐文章