Separate out collections extensions

Even though there are relatively few collections extensions right now, there is a relatively high chance that other extension will be used in the future.
This commit is contained in:
Matt Nadareski
2026-03-23 10:50:09 -04:00
parent 1f1a5c51f3
commit 77dc8ebed7
14 changed files with 108 additions and 7 deletions

View File

@@ -1,33 +0,0 @@
using System.Collections.Generic;
namespace SabreTools.IO.Extensions
{
public static class DictionaryExtensions
{
/// <summary>
/// Merge a dictionary into an existing one, if possible
/// </summary>
/// <param name="dict">Source dictionary to add to</param>
/// <param name="other">Second dictionary to add from</param>
/// <remarks>This only performs a shallow copy</remarks>
public static void MergeWith(this Dictionary<string, List<string>> dict, Dictionary<string, List<string>> other)
{
// Ignore if there are no values to append
if (other.Count == 0)
return;
// Loop through and add from the new dictionary
foreach (var kvp in other)
{
// Ignore empty values
if (kvp.Value.Count == 0)
continue;
if (!dict.ContainsKey(kvp.Key))
dict[kvp.Key] = [];
dict[kvp.Key].AddRange(kvp.Value);
}
}
}
}

View File

@@ -1,76 +0,0 @@
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;
}
}
}
}

View File

@@ -2,6 +2,7 @@
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using SabreTools.Collections.Extensions;
using SabreTools.Text.Compare;
namespace SabreTools.IO.Extensions

View File

@@ -2,7 +2,7 @@
This library contains IO-related extensions with some functionality locked behind .NET version support.
Relies on functionality found in `SabreTools.IO.Matching`, `SabreTools.Numerics`, and `SabreTools.Text.Compare`.
Relies on functionality found in `SabreTools.Collections.Extensions`, `SabreTools.IO`, `SabreTools.IO.Matching`, `SabreTools.Numerics`, `SabreTools.Numerics.Extensions`, `SabreTools.Text.Compare`, and `SabreTools.Text.Extensions`.
| Class | Description |
| --- | --- |
@@ -12,8 +12,6 @@ Relies on functionality found in `SabreTools.IO.Matching`, `SabreTools.Numerics`
| `ByteArrayReaderExtensions` | Extensions to `byte[]` for specialized type reading. |
| `ByteArrayWriterExtensions` | Extensions to `byte[]` for specialized type writing. |
| `DateTimeExtensions` | `DateTime` conversion, specifically between standard and MS-DOS formats. |
| `DictionaryExtensions` | Utility `Dictionary<string, List<string>>` extensions commonly used in SabreTools projects. |
| `EnumerableExtensions` | Specialized enumeration wrapper functionality. |
| `IOExtensions` | Path, directory, and file extensions. |
| `MarshalHelpers` | Internal-only reflection-based extensions used by some other extension classes. |
| `ParentablePathExtensions` | Extensions to `SabreTools.IO.ParentablePath` for filtering. |

View File

@@ -30,6 +30,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SabreTools.Collections.Extensions\SabreTools.Collections.Extensions.csproj" />
<ProjectReference Include="..\SabreTools.IO\SabreTools.IO.csproj" />
<ProjectReference Include="..\SabreTools.Matching\SabreTools.Matching.csproj" />
<ProjectReference Include="..\SabreTools.Numerics\SabreTools.Numerics.csproj" />