diff --git a/Recyclable.Collections/IAddRangeProvider.cs b/Recyclable.Collections/IAddRangeProvider.cs new file mode 100644 index 0000000..8928381 --- /dev/null +++ b/Recyclable.Collections/IAddRangeProvider.cs @@ -0,0 +1,9 @@ +namespace Recyclable.Collections +{ + internal interface IAddRangeProvider + { + void AddRangeTo(RecyclableList list); + void AddRangeTo(RecyclableLongList list); + } +} + diff --git a/Recyclable.Collections/RecyclableDictionary.cs b/Recyclable.Collections/RecyclableDictionary.cs index 33cb849..f3d3c68 100644 --- a/Recyclable.Collections/RecyclableDictionary.cs +++ b/Recyclable.Collections/RecyclableDictionary.cs @@ -6,7 +6,7 @@ using Recyclable.Collections.Pools; namespace Recyclable.Collections { - internal sealed class RecyclableDictionary : IEnumerable>, IDisposable + internal sealed class RecyclableDictionary : IEnumerable>, IDisposable, IAddRangeProvider> where TKey : notnull { internal static readonly bool _needsClearing = !typeof(TKey).IsValueType || !typeof(TValue).IsValueType; @@ -401,5 +401,15 @@ namespace Recyclable.Collections { } } + + void IAddRangeProvider>.AddRangeTo(RecyclableList> list) + { + zRecyclableListAddRange.AddRange(list, this); + } + + void IAddRangeProvider>.AddRangeTo(RecyclableLongList> list) + { + zRecyclableLongListAddRange.AddRange(list, this); + } } } diff --git a/Recyclable.Collections/RecyclableList.AddRange.cs b/Recyclable.Collections/RecyclableList.AddRange.cs index e596115..f12696f 100644 --- a/Recyclable.Collections/RecyclableList.AddRange.cs +++ b/Recyclable.Collections/RecyclableList.AddRange.cs @@ -1,71 +1,11 @@ using System.Collections; using System.Numerics; using System.Runtime.CompilerServices; -using System.Linq.Expressions; -using System.Reflection; namespace Recyclable.Collections { public static class zRecyclableListAddRange { - private static class AddRangeHelper - { - internal static readonly Type? DictionaryType; - internal static readonly Type? SortedListType; - internal static readonly Action, IEnumerable>? DictionaryAdder; - internal static readonly Action, IEnumerable>? SortedListAdder; - - static AddRangeHelper() - { - var itemType = typeof(T); - if (itemType.IsGenericType) - { - var genericDefinition = itemType.GetGenericTypeDefinition(); - if (genericDefinition == typeof(KeyValuePair<,>)) - { - var args = itemType.GetGenericArguments(); - DictionaryType = typeof(RecyclableDictionary<,>).MakeGenericType(args); - - var listType = typeof(RecyclableList<>).MakeGenericType(itemType); - var method = typeof(zRecyclableListAddRange).GetMethod( - nameof(AddRange), - BindingFlags.NonPublic | BindingFlags.Static, - null, - new[] { listType, DictionaryType }, - null)!.MakeGenericMethod(args); - - var listParam = Expression.Parameter(typeof(RecyclableList), "list"); - var itemsParam = Expression.Parameter(typeof(IEnumerable), "items"); - var call = Expression.Call(method, - Expression.Convert(listParam, listType), - Expression.Convert(itemsParam, DictionaryType)); - - DictionaryAdder = Expression.Lambda, IEnumerable>>(call, listParam, itemsParam).Compile(); - } - else if (genericDefinition == typeof(ValueTuple<,>)) - { - var args = itemType.GetGenericArguments(); - SortedListType = typeof(RecyclableSortedList<,>).MakeGenericType(args); - - var listType = typeof(RecyclableList<>).MakeGenericType(itemType); - var method = typeof(zRecyclableListAddRange).GetMethod( - nameof(AddRange), - BindingFlags.NonPublic | BindingFlags.Static, - null, - new[] { listType, SortedListType }, - null)!.MakeGenericMethod(args); - - var listParam = Expression.Parameter(typeof(RecyclableList), "list"); - var itemsParam = Expression.Parameter(typeof(IEnumerable), "items"); - var call = Expression.Call(method, - Expression.Convert(listParam, listType), - Expression.Convert(itemsParam, SortedListType)); - - SortedListAdder = Expression.Lambda, IEnumerable>>(call, listParam, itemsParam).Compile(); - } - } - } - } private static void AddRangeEnumerated(this RecyclableList list, IEnumerable items, int growByCount) { @@ -638,13 +578,9 @@ namespace Recyclable.Collections { AddRange(list, sourceQueue); } - else if (AddRangeHelper.DictionaryAdder != null && AddRangeHelper.DictionaryType!.IsInstanceOfType(items)) + else if (items is IAddRangeProvider provider) { - AddRangeHelper.DictionaryAdder!(list, items); - } - else if (AddRangeHelper.SortedListAdder != null && AddRangeHelper.SortedListType!.IsInstanceOfType(items)) - { - AddRangeHelper.SortedListAdder!(list, items); + provider.AddRangeTo(list); } else if (items is IReadOnlyList sourceIReadOnlyList) { diff --git a/Recyclable.Collections/RecyclableLongList.AddRange.cs b/Recyclable.Collections/RecyclableLongList.AddRange.cs index 321e28b..825963b 100644 --- a/Recyclable.Collections/RecyclableLongList.AddRange.cs +++ b/Recyclable.Collections/RecyclableLongList.AddRange.cs @@ -1,72 +1,12 @@ using System.Collections; using System.Numerics; using System.Runtime.CompilerServices; -using System.Linq.Expressions; -using System.Reflection; using Recyclable.Collections.Pools; namespace Recyclable.Collections { public static class zRecyclableLongListAddRange { - private static class AddRangeHelper - { - internal static readonly Type? DictionaryType; - internal static readonly Type? SortedListType; - internal static readonly Action, IEnumerable>? DictionaryAdder; - internal static readonly Action, IEnumerable>? SortedListAdder; - - static AddRangeHelper() - { - var itemType = typeof(T); - if (itemType.IsGenericType) - { - var genericDefinition = itemType.GetGenericTypeDefinition(); - if (genericDefinition == typeof(KeyValuePair<,>)) - { - var args = itemType.GetGenericArguments(); - DictionaryType = typeof(RecyclableDictionary<,>).MakeGenericType(args); - - var listType = typeof(RecyclableLongList<>).MakeGenericType(itemType); - var method = typeof(zRecyclableLongListAddRange).GetMethod( - nameof(AddRange), - BindingFlags.NonPublic | BindingFlags.Static, - null, - new[] { listType, DictionaryType }, - null)!.MakeGenericMethod(args); - - var listParam = Expression.Parameter(typeof(RecyclableLongList), "list"); - var itemsParam = Expression.Parameter(typeof(IEnumerable), "items"); - var call = Expression.Call(method, - Expression.Convert(listParam, listType), - Expression.Convert(itemsParam, DictionaryType)); - - DictionaryAdder = Expression.Lambda, IEnumerable>>(call, listParam, itemsParam).Compile(); - } - else if (genericDefinition == typeof(ValueTuple<,>)) - { - var args = itemType.GetGenericArguments(); - SortedListType = typeof(RecyclableSortedList<,>).MakeGenericType(args); - - var listType = typeof(RecyclableLongList<>).MakeGenericType(itemType); - var method = typeof(zRecyclableLongListAddRange).GetMethod( - nameof(AddRange), - BindingFlags.NonPublic | BindingFlags.Static, - null, - new[] { listType, SortedListType }, - null)!.MakeGenericMethod(args); - - var listParam = Expression.Parameter(typeof(RecyclableLongList), "list"); - var itemsParam = Expression.Parameter(typeof(IEnumerable), "items"); - var call = Expression.Call(method, - Expression.Convert(listParam, listType), - Expression.Convert(itemsParam, SortedListType)); - - SortedListAdder = Expression.Lambda, IEnumerable>>(call, listParam, itemsParam).Compile(); - } - } - } - } private static void AddRangeEnumerated(this RecyclableLongList targetList, IEnumerable items) { @@ -499,12 +439,8 @@ namespace Recyclable.Collections targetList.AddRange(sourceQueue); return; - case var _ when AddRangeHelper.DictionaryAdder != null && AddRangeHelper.DictionaryType!.IsInstanceOfType(items): - AddRangeHelper.DictionaryAdder!(targetList, items); - return; - - case var _ when AddRangeHelper.SortedListAdder != null && AddRangeHelper.SortedListType!.IsInstanceOfType(items): - AddRangeHelper.SortedListAdder!(targetList, items); + case IAddRangeProvider provider: + provider.AddRangeTo(targetList); return; default: diff --git a/Recyclable.Collections/RecyclableSortedList.cs b/Recyclable.Collections/RecyclableSortedList.cs index 9b371ea..b11ca58 100644 --- a/Recyclable.Collections/RecyclableSortedList.cs +++ b/Recyclable.Collections/RecyclableSortedList.cs @@ -5,7 +5,7 @@ using Recyclable.Collections.Pools; namespace Recyclable.Collections { - internal sealed class RecyclableSortedList : IEnumerable<(TKey Key, TValue Value)>, IDisposable + internal sealed class RecyclableSortedList : IEnumerable<(TKey Key, TValue Value)>, IDisposable, IAddRangeProvider<(TKey Key, TValue Value)> where TKey : notnull { internal static readonly bool _needsClearing = !typeof(TKey).IsValueType || !typeof(TValue).IsValueType; @@ -276,5 +276,15 @@ namespace Recyclable.Collections { } } + + void IAddRangeProvider<(TKey Key, TValue Value)>.AddRangeTo(RecyclableList<(TKey Key, TValue Value)> list) + { + zRecyclableListAddRange.AddRange(list, this); + } + + void IAddRangeProvider<(TKey Key, TValue Value)>.AddRangeTo(RecyclableLongList<(TKey Key, TValue Value)> list) + { + zRecyclableLongListAddRange.AddRange(list, this); + } } }