Foreach中更清洁的错误处理

问题描述

| 我正在发生一些foreach循环。发生了什么事,我正在从GPS设备获取航班列表。因此,在第一个循环中,我正在解析n个航班的标头详细信息字符串。 然后,对于每次飞行,我查询一个设备以获取原始GPS数据。 所以:
    foreach(var flight in flightList)
{
   var samples = GetRawGPSDataIntoAString();
   foreach(var line in samples)
   {
      var line = splitTheSampleIntoAlistofStrings();
      foreach(var sampleSection is line)
      {
         DoSomeStuff();
      }
   }
}
我的问题是,如果我检测到内部循环中的某些问题,我想将一些数据记录到日志文件中(完成),然后退出内部循环,因为\'line \'格式错误。 然后,我也想退出第二循环,因为现在继续进行示例是毫无意义的。然后,我想通知用户航班有无效的数据,并询问他们是否要继续加载其余航班。如果他们回答“是”,我希望下一个外部循环进入下一个循环。 我目前没有错误处理...因此,我将尝试/除非在我知道它可能会失败的区域...尤其是在分割字符串(以逗号分隔)然后进行危险的操作的地方, \'string gpsCoord = line [2] \'。如果在'split \'期间出现错误,则有可能导致索引超出范围问题。 (我同意,我可以首先检查\'line \'中是否有足够的项目,但是我不确定如何一次中止两个\'foreach \'循环,从而将控制权返回到外部循环。 希望我有点道理..     

解决方法

        每当您要终止多个嵌套循环时,通常最好将每个循环置于自己的函数中:
private static bool ProcessLine(string line)
{
    try
    {
        var sampleSections = splitTheSampleIntoAListOfStrings();
        foreach( var sampleSection in line )
        {
            DoSomeStuff();
        }
        return true;
    }
    catch( SomeException ex )
    {
        LogError(ex);
        return false;
    }
}

private static void ProcessSamples(FlightType flight)
{
    var samples = GetRawGPSDataIntoAString(flight);
    foreach( var line in samples )
    {
        if( !ProcessLine(line) )
            return;
    }
}

private static void ProcessFlights()
{
    foreach( var flight in flightList )
    {
        ProcessSamples(flight);
    }
}
这使得摆脱某些嵌套循环并继续其他循环变得非常容易,而不必使用诸如退出标志之类的混乱构造。由于减少了嵌套级别,因此代码也更易于阅读。     ,        听起来您对“重新抛出”异常的能力感兴趣:
foreach(var flight in flightList)
{
   try {
       var samples = GetRawGPSDataIntoAString();
       foreach(var line in samples)
       {
          var line = splitTheSampleIntoAListOfStrings();
          foreach(var sampleSection in line)
          {
             try {
                 DoSomeStuff();
             }
             catch(Exception ex) {
                 log(ex);
                 throw; // <--- HERE,we didn\'t solve the problem
                        // so we let the exception reach the next catch
             }
          }
       }
       catch (ContinuableException ex2) { /* ignore and keep trying */ }
   }
}
我将其拆分为多个功能,但一个功能中的两个try / catch块太多了。这是无需重新抛出的另一种方法:
foreach(var flight in flightList)
{
    var samples = GetRawGPSDataIntoAString();
    ProcessSamples(samples);
}

ProcessSamples(samples) // fix the return type and parameter type,of course
{
   foreach(var line in samples)
   {
      var line = splitTheSampleIntoAListOfStrings();
      foreach(var sampleSection in line)
      {
         try {
             DoSomeStuff();
         }
         catch(Exception ex) {
             log(ex);
             return; // exits two loops at once
         }
      }
   }
}
    ,        你可以做这样的事情
bool exitFlag = false;
foreach(var flight in flightList)
{
   foreach(var line in samples)
   {
      if(exitFlag){
               exitFlag = false;
               break;
      }
      var samples = GetRawGPSDataIntoAString();
      var line = splitTheSampleIntoAListOfStrings();
      foreach(var sampleSection is line)
      {
         try{
             DoSomeStuff();
          }
          catch(*the exception you expect* e){
                 Log(e); // do some logging
                 exitFlag = true;   
                 break;
          }
      }
   }
}