IEnumerable keys doesn't work
Hi there! thanx for awesome project! It makes my unity development much easier :tada:
well, I'm trying to create GenericDictionary<string[], string> in my project, however it doesn't work - reffering to the key always returns KeyNotFound exception.
Atm, I'm working it around by using this code:
foreach (var key in myDict.Keys)
if (key.SequenceEqual(query))
{
Debug.Log("query found");
}
but it would be nice to have it in the package
Hey thanks!
Using arrays as keys is something I've never tried, but I suspect since you can't have arrays of arrays in Unity inspector this is most likely what it boils down to.
I would probably suggest laying out your data in some other way that might end up being more logical, but I suppose there are use cases where an array is the key is the most logical layout, it's just that Unity doesn't support this and by extension this project neither.
I'll leave this open and mull it around the old nogging and see if I can come up with something in the meantime.
Thanks again for your support!
but I suspect since you can't have arrays of arrays in Unity inspector this is most likely what it boils down to.
no, it is possible to have array of arrays in unity inspector
(at least since 2020.3.22, which i'm running on)
Okay cool I didn't know this works, I'll have a look and see if I can make this use case work nicely!
thank you! looking forward to see the solution ;-)
Hey again sorry for taking time to get back to you!
I've tested this out today and it seems to work as intended from what I can tell:
public GenericDictionary<string[], string> dict; // populated in inspector with key { "a", "b", "c" }
void Start()
{
print(dict.ContainsKey(new string[]{ "a", "b", "c"})); // prints false since I create a new object that doesn't refer to the one created in inspector
var keyEnumerator = dict.Keys.GetEnumerator();
keyEnumerator.MoveNext();
print(dict.ContainsKey(keyEnumerator.Current)); // prints true since the object reference is correct
}
I see that SequenceEquals checks equality using the type's default equality comparer per element.
This dictionary also uses each types default equality comparer, but does so per Key (regardless if key is enumerable or not).
I guess I could add branching that would check if the Key type is enumerable and then perform per element comparisons to check for equality.
But this is opinionated and would conversely break for someone expecting reference equality rather than value equality.
Are you still using this implementation with string[] as Key and would like to see this change? Perhaps it's an opinion that should be implemented, but I'd rather tread slowly and hear peoples thoughts on this first.
Anyways thanks for your support and encouraging me to get back at improving this project!
I tested this out some more and see what you mean, looking in the inspector it seems logical that enumerable keys should be value based rather than reference based (notice there's no warning about duplicate keys):

I'm not sure if there are edge cases where you do want reference based enumerable types though so I'm investigating this closer.
Regardless it seems the dictionary key lookup would go from ~O(1) to O(N) when using enumerable key types, but I suppose there's no way around that?
Quick follow up.
I've found that it's quite easy to check if the key is enumerable (serializedProperty.isArray) - but this flag is true for strings, so I'm wary that there are other properties that behave this way.
Currently the best solution for having enumerable keys would probably be to create a class and override the Equals and GetHashCode methods to get the desired behavior. This way the user can choose, with the drawback of added ceremony whenever enumerable keys with value based comparisons are desired.
I'll be digging a bit deeper though so will leave this issue opened.