【问题标题】:Return value from For loopFor 循环的返回值
【发布时间】:2011-11-25 12:09:43
【问题描述】:

我的应用中有一个 listView。我遍历项目以检查当前选择了哪个项目,然后返回一个值。由于所有路径都必须返回一个值,我必须在循环外返回一个值,该值会覆盖 for 循环返回,如何在循环后保持它而不覆盖它?

public string GetItemValue()
{
    for (int i = 0; i < listView1.Items.Count; i++)
    {
        if (listView1.Items[i].Checked == true)
        {
            return listView1.Items[i].Text; // I want to keep this value
        }
     }
     // Without overwriting it with this but the compiler 
     // requires me to return a value here
     return "Error"; 
}

非常感谢任何帮助。谢谢。

P.S 我曾尝试在 if 之后使用 break,但没有运气。

【问题讨论】:

  • 你不必担心这个。一旦它到达循环内的第一个return,它将立即返回该值。在这种情况下,不会命中循环外的任何代码。
  • 你试过看看到底发生了什么吗?
  • 当我运行它时,它只是返回错误文本...
  • @Bali C 你检查过一个项目吗?打破它以确保您的 if 语句得到执行。
  • @BaliC 如果它返回错误文本,那么你在循环中的if 条件永远不会通过。

标签: c# winforms for-loop return


【解决方案1】:

编辑时:从上面删除我的评论。

您无需担心这一点。一旦它到达循环内的第一个return,它将立即返回该值。在这种情况下,不会命中循环外的任何代码。

顺便说一句,这段代码会更简洁:

public string GetItemValue()
{
    foreach (var item in listView1.Items)
    {
        if (item.Checked) return item.Text;
    }
    throw new InvalidOperationException("No checked items found");
}

异常是一种更惯用的错误处理方式,当您只是迭代集合时,foreach 循环优于 for 循环。

同样使用 LINQ,你可以得到更简洁:

public string GetItemValue()
{
    return listView1.Items.Cast<ListViewItem>().Single(i => i.Checked).Text;
}

【讨论】:

  • 把new Exception()改成更具体的类型,在第二个例子中加一个Cast(),就完美了。 ;-)
  • 好点。我忘记了 Windows 窗体对象返回非通用容器。令人遗憾的是,所有这些旧的小部件仍然完好无损地闲逛!
【解决方案2】:

好吧,根据您的逻辑,您在循环之外的返回 return "Error"; 不应该被调用。由于return 会导致您的方法立即退出,因此永远不会发生“错误”返回,除非代码永远 进入循环内的if。

考虑到所有因素,这可能是您的代码中的一个异常情况。因此,抛出异常可能是合适的做法:

public string GetItemValue()
        {
            for (int i = 0; i < listView1.Items.Count; i++)
            {
                if (listView1.Items[i].Checked == true)
                {
                    return listView1.Items[i].Text; // I want to keep this value
                }
            }
            throw new InvalidOperationException("Did not find value expected.");
        }

通常会抛出异常以指示代码中存在错误。 “嘿,那真的不应该发生。”应用程序停止,希望用户有机会联系支持人员以帮助您重现它。

基于your comment:

当我运行它时,它只是返回错误文本...

这意味着您在if 语句中的检查不成功。

if (listView1.Items[i].Checked == true)

这意味着您的 ListView 中的所有项目都不会被检查。

【讨论】:

    【解决方案3】:

    在这种情况下,您最好抛出异常以发出异常情况的信号:

    public string GetItemValue()
    {
        for (int i = 0; i < listView1.Items.Count; i++)
        {
            if (listView1.Items[i].Checked == true)
            {
                // Here you are leaving the GetItemValue method
                // and the loop stops
                return listView1.Items[i].Text;
            }
        }
        // if we get that far it means that none of the items of
        // the select list was actually checked => we are better of
        // reporting this to the caller of the method
        throw new Exception("Please select a value");
    }
    

    【讨论】:

      【解决方案4】:

      for 循环中的返回值不会被覆盖——如果满足您的条件,该方法将返回循环中的值。该方法的执行在到达return 语句后立即结束。

      如果您的方法返回“错误”,那么我建议您在调试器中查看您的代码,因为它已到达循环末尾并返回值“错误”。

      【讨论】:

        【解决方案5】:

        如果你在循环中返回一个值,它不应该到达循环外的返回值。我会检查以确保循环正在查找所选项目。

        另一种选择是创建一个局部变量来保存返回值:

        string returnValue = "Error";
        
        for (int i = 0; i < listView1.Items.Count; i++) 
        { 
            if (listView1.Items[i].Checked == true) 
            { 
                returnValue = listView1.Items[i].Text;
                break;
            } 
        } 
        
        return returnValue;
        

        最后,您还可以考虑在未找到选择时返回异常,并从调用方法处理异常。

        【讨论】:

          【解决方案6】:

          return "Error" 位不会覆盖您的循环返回值。当return被命中时,函数退出,所以当找到一个被选中的值时,函数将吐出你的数据并停止。

          【讨论】:

            【解决方案7】:

            编译器要求函数的所有路径都返回一个值。编译器无法事先知道您的内部循环是否会满足条件。您可以将值缓存在变量中并在函数末尾返回它,例如:

            public string GetItemValue()
                {
                    string temp = null;
                    for (int i = 0; i < listView1.Items.Count; i++)
                    {
                        if (listView1.Items[i].Checked == true)
                        {
                            temp = listView1.Items[i].Text; // I want to keep this value
                            break;
                        }
                    }
                    return temp; // Without overwriting it with this but the compiler requires me to return a value here
                }
            

            【讨论】:

            • 这是错误的。编译器将出于与原始代码相同的原因拒绝此操作 - temp 变量尚未明确分配值。
            【解决方案8】:

            其实这里不需要循环:

            return (listView1.SelectedItems.Count > 0)
                ? listView1.SelectedItems[0].Text
                : "Error";
            

            但是,正如人们所说,最初的问题具有误导性,因为return 不会覆盖值。您可能正在考虑分配,而不是返回。在这种情况下,工作代码可能如下所示:

            string ret = "Error";
            foreach(var item in listView1.Items)
            {
                if(item.Checked) { ret = item.Text; break; }
            }
            
            return ret;
            

            【讨论】:

              猜你喜欢
              • 2016-09-03
              • 1970-01-01
              • 2016-08-23
              • 2019-04-24
              • 1970-01-01
              • 1970-01-01
              • 2011-07-05
              • 1970-01-01
              • 2015-12-30
              相关资源
              最近更新 更多