Files
SabreTools.IO/SabreTools.IO.Extensions/EnumerableExtensions.cs
Matt Nadareski d614379cf5 Libraries
This change looks dramatic, but it's just separating out the already-split namespaces into separate top-level folders. In theory, every single one could be built into their own Nuget package. `SabreTools.IO.Meta` builds the normal Nuget package that is used by all other projects and includes all namespaces. `SabreTools.IO` builds to `SabreTools.IO.Common` to avoid overwriting issues on publish.
2026-03-21 13:55:42 -04:00

77 lines
2.2 KiB
C#

using System;
using System.Collections.Generic;
namespace SabreTools.IO.Extensions
{
public static class EnumerableExtensions
{
/// <summary>
/// Wrap iterating through an enumerable with an action
/// </summary>
/// <remarks>
/// .NET Frameworks 2.0 and 3.5 process in series.
/// .NET Frameworks 4.0 onward process in parallel.
/// </remarks>
public static void IterateWithAction<T>(this IEnumerable<T> source, Action<T> action)
{
#if NET20 || NET35
foreach (var item in source)
{
action(item);
}
#else
System.Threading.Tasks.Parallel.ForEach(source, action);
#endif
}
/// <summary>
/// Safely iterate through an enumerable, skipping any errors
/// </summary>
public static IEnumerable<T> SafeEnumerate<T>(this IEnumerable<T> enumerable)
{
// Get the enumerator for the enumerable
IEnumerator<T> enumerator;
try
{
enumerator = enumerable.GetEnumerator();
}
catch
{
yield break;
}
// Iterate through and absorb any errors
while (true)
{
// Attempt to move to the next item
bool moved;
try
{
moved = enumerator.MoveNext();
}
catch (InvalidOperationException)
{
// Specific case for collections that were modified
yield break;
}
catch (System.IO.IOException ex) when (ex.Message.Contains("The file or directory is corrupted and unreadable."))
{
// Specific case we can't circumvent
yield break;
}
catch
{
continue;
}
// If the end of the enumeration is reached
if (!moved)
yield break;
// Return the next value from the enumeration
yield return enumerator.Current;
}
}
}
}