godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.04k stars 65 forks source link

Godot's Dictionary and C# builtin Dictionary Hash behaviors should be consistent #9587

Closed KarryCharon closed 1 week ago

KarryCharon commented 1 week ago

Describe the project you are working on

-

Describe the problem or limitation you are having in your project

C# builtin Dictionary and Godot's Dictionary hash behaviors are not consistent.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

// GameplayTag has override GetHashCode and equal == != operators!
var tag1 = new GameplayTag("Player.Skill.Attack");
var tag2 = new GameplayTag("Player.Skill.Attack");
bool IsEqual1 = tag1 == tag2; // True
bool IsEqual2 = tag1.Equals(tag2); // True
bool IsHashCodeEqual = tag1.GetHashCode() == tag2.GetHashCode(); // True
var d1 = new System.Collections.Generic.Dictionary<GameplayTag, int>();
d1.Add(tag1, 1);
var d2 = new Godot.Collections.Dictionary<GameplayTag, int>();
d2.Add(tag1, 1);
bool IsInD1 = d1.ContainsKey(tag2); // True
bool IsInD2 = d2.ContainsKey(tag2); // False (Should be True)

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

-

If this enhancement will not be used often, can it be worked around with a few lines of script?

-

Is there a reason why this should be core and not an add-on in the asset library?

-

raulsntos commented 1 week ago

Godot collections don't use any of the C# comparison/equality methods (GetHashCode, Equals, == or !=).

When calling Godot.Collections.Dictionary.ContainsKey it just calls the native C++ implementation of the Dictionary::has method which uses the Variant hasher. For GodotObject and derived types this means calculating a hash from the object's pointer, so naturally different instances will have a different hash.

I'm not aware of any way to override this, so you'll have to convert the Godot collection to a C# collection if you want to use the C# comparison/equality.

KarryCharon commented 1 week ago

Godot collections don't use any of the C# comparison/equality methods (GetHashCode, Equals, == or !=).

When calling Godot.Collections.Dictionary.ContainsKey it just calls the native C++ implementation of the Dictionary::has method which uses the Variant hasher. For GodotObject and derived types this means calculating a hash from the object's pointer, so naturally different instances will have a different hash.

I'm not aware of any way to override this, so you'll have to convert the Godot collection to a C# collection if you want to use the C# comparison/equality.

C# builtin Dictionary cant be export to Inspector, Godot's Dictionary cant rewrite hash for ContainsKey. Both of them are important for me. :(