Every time you are concatenating strings to use as a unified key, you are creating garbage for the garbage collector. This has a performance impact that is not trivial to measure, because you dοn't pay the price instantly. You are paying it when the garbage collection kicks in, and has more work to do than usual. Concatenating strings is also not a bullet proof approach, because it is based on the assumption that the delimiter (the pipe character in your example), is never contained in any of the subkeys.
My suggestion is to use value tuples as keys. For example in case each key is composed of 3 string parts, you could declare your dictionary like this:
Dictionary<(string, string, string), MyItem> dictionary = new();
//...
dictionary.Add(("key1", "key2", "key3"), new MyItem());
//...
if (dictionary.TryGetValue(("key1", "key2", "key3"), out var item)) //...
This will search for the keys with case sensitivity. In case you prefer your searches to be case insensitive, you could create a custom comparer that implements the IEqualityComparer<(string, string, string)>
interface, implement accordingly the Equals
and GetHashCode
methods (look here for an example), and pass an instance to the constructor of the dictionary. You'll probably have to use the StringComparer.OrdinalIgnoreCase
in the implementation.
Another option is to install the Nito.Comparers package, and create your comparer fluently like this:
var myComparer = Nito.Comparers.EqualityComparerBuilder
.For<(string, string, string)>()
.EquateBy(x => x.Item1, StringComparer.OrdinalIgnoreCase)
.ThenEquateBy(x => x.Item2, StringComparer.OrdinalIgnoreCase)
.ThenEquateBy(x => x.Item3, StringComparer.OrdinalIgnoreCase);