Is there an existing issue for this?
Task description
Now that J2N has alternate lookup functionality implemented, we can utilize it to make extension methods that make syntax seamless when converting values from string to ReadOnlySpan<char>. For now, let's keep the implementation minimal and expand it as needed. There are a few APIs that we will almost certainly need that we can implement now to set a precedent for any others that may be added later, as needed.
Proposed API
namespace Lucene.Net.Support
{
internal static class DictionaryExtensions
{
public static bool TryAdd(this IDictionary<string, TValue> dictionary, ReadOnlySpan<char> key, TValue value);
public static bool ContainsKey(this IDictionary<string, TValue> dictionary, ReadOnlySpan<char> key);
public static bool TryGetValue(this IDictionary<string, TValue> dictionary, ReadOnlySpan<char> key, [MaybeNullWhen(false)] out TValue value);
public static bool TryGetValue(ReadOnlySpan<char> key, [MaybeNullWhen(false)] out TKey actualKey, [MaybeNullWhen(false)] out TValue value);
public static TValue Put<string, TValue>(this IDictionary<string, TValue> dictionary, ReadOnlySpan<char> key, TValue value);
public static bool Remove(this IDictionary<string, TValue> dictionary, ReadOnlySpan<char> key);
}
internal static class SetExtensions
{
public static bool Add(this ISet<string> set, ReadOnlySpan<char> item);
public static bool Contains(this ISet<string> set, ReadOnlySpan<char> item);
public static bool TryGetValue(this ISet<string> set, ReadOnlySpan<char> equalValue, [MaybeNullWhen(false)] out T actualValue);
public static bool Remove(this ISet<string> set, ReadOnlySpan<char> item);
}
}
Note that these interface overloads will be used in many situations because Lucene.NET primarily passes interfaces, however, we can also include overloads for
JCG.Dictionary<TKey, TValue>
JCG.OrderedDictionary<TKey, TValue>
JCG.SortedDictionary<TKey, TValue>
JCG.HashSet<T>
JCG.OrderedHashSet<T>
JCG.SortedSet<T>
This would rely on the compiler for direct calls in many cases, which would save a lot of type comparison overhead for those callers.
We can also include BCL types in target frameworks that support alternate lookup, but we probably should just include those optimizations in the IDictionary<TKey, TValue> and ISet<T> implementations rather than going through the effort to make extra overloads.
We should also optimize the existing Put() extension method to use CollectionMarshal/CollectionsMarshal where supported, since it will eliminate an extra lookup from our current implementation (which does 2 lookups).
The interface overloads should fall back to using a collection scan for small collections or a key allocation for large collections over 64 elements. We should also put Debugging.Assert() calls just before the slow path so we don't accidentally call it in any of the code that we ship. Now that we have low-level collection implementations (except for ConcurrentDictionary<TKey, TValue>), we should be using them exclusively.
Is there an existing issue for this?
Task description
Now that J2N has alternate lookup functionality implemented, we can utilize it to make extension methods that make syntax seamless when converting values from
stringtoReadOnlySpan<char>. For now, let's keep the implementation minimal and expand it as needed. There are a few APIs that we will almost certainly need that we can implement now to set a precedent for any others that may be added later, as needed.Proposed API
Note that these interface overloads will be used in many situations because Lucene.NET primarily passes interfaces, however, we can also include overloads for
JCG.Dictionary<TKey, TValue>JCG.OrderedDictionary<TKey, TValue>JCG.SortedDictionary<TKey, TValue>JCG.HashSet<T>JCG.OrderedHashSet<T>JCG.SortedSet<T>This would rely on the compiler for direct calls in many cases, which would save a lot of type comparison overhead for those callers.
We can also include BCL types in target frameworks that support alternate lookup, but we probably should just include those optimizations in the
IDictionary<TKey, TValue>andISet<T>implementations rather than going through the effort to make extra overloads.We should also optimize the existing
Put()extension method to useCollectionMarshal/CollectionsMarshalwhere supported, since it will eliminate an extra lookup from our current implementation (which does 2 lookups).The interface overloads should fall back to using a collection scan for small collections or a key allocation for large collections over 64 elements. We should also put
Debugging.Assert()calls just before the slow path so we don't accidentally call it in any of the code that we ship. Now that we have low-level collection implementations (except forConcurrentDictionary<TKey, TValue>), we should be using them exclusively.