【问题标题】:Cleanest way to skip record in foreach based on condition根据条件在 foreach 中跳过记录的最干净方法
【发布时间】:2019-11-05 15:47:41
【问题描述】:

我有一个嵌套的 foreach 循环,我想知道根据 c# 中的 if 条件跳过记录的最佳方法。

以下是我的解决方案,如果有任何改进或建议,请告诉我。

foreach (var ospMap in sourceSpecificMaps)
{
    foreach (var idMapSensorId in ospMap.SensorIds)
    {
        try
        {
            if (string.IsNullOrEmpty(idMapSensorId.SourceId))
            {
                throw new Exception($"SourceId couldn't be found in the { idMapSensorId.SensorId } sensor. The sensor is being skiped.");
            }
            _ospIdMapDictionary[GenCacheId(sourceId, idMapSensorId.SensorId)] = ospMap;
       }
       catch (Exception)
       {
            // We continue through the loop
            continue;
       }  
    }
}

【问题讨论】:

  • 如果你对异常什么都不做,你可以把continue;放在if语句中
  • 除了您抛出的异常之外,您是否期望任何其他异常?
  • 您如何在 C# 中使用 C++ 库“boost-foreach”?
  • 去掉try/catch,把continue放到if中。如果“干净”和“聪明”被证明是相互排斥的,那么您对“聪明”的定义就严重错误了。
  • 看起来像一个简单的.SelectMany(...).Where(...).ToDictionary(...),假设这会创建整个字典。

标签: c# foreach .net-core boost-foreach


【解决方案1】:

使用这样的异常既慢(异常非常慢)又糟糕的做法。如果您想跳过,只需使用 continue 即可。

foreach (var ospMap in sourceSpecificMaps)
{
  foreach (var idMapSensorId in ospMap.SensorIds)
  {
    if (string.IsNullOrEmpty(idMapSensorId.SourceId))
    {
      continue; // TODO: Log the follwoing ?  SourceId couldn't be found in the { idMapSensorId.SensorId } sensor. The sensor is being skiped
    }
    _ospIdMapDictionary[GenCacheId(sourceId, idMapSensorId.SensorId)] = ospMap;
  }

}

【讨论】:

    【解决方案2】:

    您正在使用异常来控制逻辑流,这通常是个坏主意。除非你真的打算对那个异常做些什么,否则去掉它,把 continue 放在那个 if 语句中。

    【讨论】:

      【解决方案3】:

      我认为,如果您不需要将 try catch 用于逻辑过程,则可以删除它,

      然后你会得到这样的代码:

      foreach (var ospMap in sourceSpecificMaps)
      {
          foreach (var idMapSensorId in ospMap.SensorIds)
          {
      
                  if (string.IsNullOrEmpty(idMapSensorId.SourceId))
                  {
                       continue; // SourceId couldn't be found in the { idMapSensorId.SensorId } sensor. The sensor is being skiped
                  }
                  _ospIdMapDictionary[GenCacheId(sourceId, idMapSensorId.SensorId)] = ospMap;
      
          }
      }
      

      【讨论】:

        【解决方案4】:

        使用 linq,您可以执行以下操作:

        var list = outerList.SelectMany(x => x.TheInnerList).Where(n => !string.IsNullOrEmpty(n.Id));

        我认为根据初始条件迭代这些元素是完成这项工作的最干净的方法

        【讨论】:

          【解决方案5】:

          你想要的是这样的:

          foreach (var ospMap in sourceSpecificMaps)
          {
              foreach (var idMapSensorId in ospMap.SensorIds)
              {
                  if (string.IsNullOrEmpty(idMapSensorId.SourceId))
                  {
                      // SourceId couldn't be found in the sensor. The sensor is being skipped.
                      continue;
                  }
                  _ospIdMapDictionary[GenCacheId(sourceId, idMapSensorId.SensorId)] = ospMap; 
              }
          }
          

          正如上面每个人都提到的,除非您抛出异常并且正确处理由异常引起的错误条件的唯一方法是在循环之外的某个地方捕获,否则不要将异常用于控制流。与简单的条件测试相比,它们极其缓慢且资源密集。尤其是在循环中,如果您获得大量空的 sourceId,这种方法可能会严重影响您的应用性能。

          在您的示例中,正如其他人所说,您实际上并没有“处理”异常。您只是忽略它并在“if”语句之后跳过循环的剩余主体。上面的代码产生了完全相同的行为。

          【讨论】:

            猜你喜欢
            • 2011-03-27
            • 2015-11-09
            • 2021-09-19
            • 2011-01-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多