根据条件跳过foreach中记录的最干净方法

Cleanest way to skip record in foreach based on condition

我有一个嵌套的 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 语句里。

如果逻辑过程不需要 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;

    }
}

像这样使用异常既慢(异常非常慢)又糟糕。如果您想跳过,请使用继续。

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;
  }

}

使用 linq 你可以做这样的事情:

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

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

你想要的是这样的:

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,这种方法可能会严重影响您的应用程序性能。

在你的例子中,正如其他人所说,你实际上 'handling' 并不是例外。您只是忽略它并跳过 'if' 语句之后的剩余循环体。上面的代码产生了完全相同的行为。