godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.71k stars 20.12k forks source link

C#: Connecting signal does not work when passing a Dictionary through the binds Array, however it works when passing the Dictionary with something else inside the Array #49180

Open lambferatu opened 3 years ago

lambferatu commented 3 years ago

Godot version:

3.3.2.stable Mono

OS/device including version:

OS: Windows 10 GPU: Nvidia GTX 1050 Ti Backend: OpenGL ES 3

Issue description:

Getting the error: emit_signal: Error calling method from signal 'ready': 'Node(Node.cs)::OnReady': Method not found.. mono_object_to_variant_impl: Attempted to convert an unmarshallable managed type to Variant. Name: 'KeyValuePair`2' Encoding: 21.

when trying to connect the "ready" signal and passing a Dictionary though the Array binds like this: Connect("ready", this, "OnReady", new Array(this.dict)); connecting to: void OnReady(Dictionary<string, int> newDict)

however it works when passing something else inside the array: Connect("ready", this, "OnReady", new Array(42, this.dict)); connecting to: void OnReady(int i, Dictionary<string, int> newDict) like this I still can use the dictionary, but I think it should be possible to use only the Dictionary inside the Array

Steps to reproduce:

Create a Dictionary, and an appropriate method to respond Connect the signal to the method and pass the dictonary though the binds Array

Minimal reproduction project:

Test.zip

kleonc commented 3 years ago

It has nothing to do with the signals. You're just invoking Array(IEnumerable) constructor instead of Array(params object[]). It happens because Dictionary<TKey, TValue> implements IEnumerable.

var emptyDict = new Dictionary<string, int>();
var nonEmptyDict = new Dictionary<string, int>() { { "one", 1 } };

// both invoke Array(IEnumerable) constructor:
new Array(emptyDict); // no error
new Array(nonEmptyDict); // error, can't convert KeyValuePair into Variant

// both invoke Array(params object[]) constructor:
new Array((object)emptyDict); // no error
new Array((object)nonEmptyDict); // no error

@Chaosus Not a bug.