2024-05-02 10:21:41 -04:00
|
|
|
using System;
|
2024-04-18 15:31:38 -04:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
2026-03-23 10:50:09 -04:00
|
|
|
namespace SabreTools.Collections.Extensions
|
2024-04-18 15:31:38 -04:00
|
|
|
{
|
|
|
|
|
public static class EnumerableExtensions
|
|
|
|
|
{
|
2025-09-06 15:42:48 -04:00
|
|
|
/// <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>
|
2026-07-09 09:55:39 -04:00
|
|
|
public static void IterateWithAction<TValue>(this IEnumerable<TValue> source, Action<TValue> action)
|
2025-09-06 15:42:48 -04:00
|
|
|
{
|
|
|
|
|
#if NET20 || NET35
|
|
|
|
|
foreach (var item in source)
|
|
|
|
|
{
|
|
|
|
|
action(item);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
System.Threading.Tasks.Parallel.ForEach(source, action);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-18 15:31:38 -04:00
|
|
|
/// <summary>
|
|
|
|
|
/// Safely iterate through an enumerable, skipping any errors
|
|
|
|
|
/// </summary>
|
2026-07-09 09:55:39 -04:00
|
|
|
public static IEnumerable<TValue> SafeEnumerate<TValue>(this IEnumerable<TValue> enumerable)
|
2024-04-18 15:31:38 -04:00
|
|
|
{
|
|
|
|
|
// Get the enumerator for the enumerable
|
2026-07-09 09:55:39 -04:00
|
|
|
IEnumerator<TValue> enumerator;
|
2024-05-02 10:25:53 -04:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
enumerator = enumerable.GetEnumerator();
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
yield break;
|
|
|
|
|
}
|
2024-04-18 15:31:38 -04:00
|
|
|
|
|
|
|
|
// Iterate through and absorb any errors
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
// Attempt to move to the next item
|
|
|
|
|
bool moved;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
moved = enumerator.MoveNext();
|
|
|
|
|
}
|
2024-05-02 10:21:41 -04:00
|
|
|
catch (InvalidOperationException)
|
|
|
|
|
{
|
|
|
|
|
// Specific case for collections that were modified
|
2024-05-02 10:26:55 -04:00
|
|
|
yield break;
|
2024-05-02 10:21:41 -04:00
|
|
|
}
|
2024-05-02 11:37:52 -04:00
|
|
|
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;
|
|
|
|
|
}
|
2024-04-18 15:31:38 -04:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-23 10:25:19 -04:00
|
|
|
}
|