Ok, I have two methods, what they do is not really important, shown below: Code (CSharp): public void RegisterDamageable(Damageable damageable, bool registerAllChildObjects = false) { RegisterDamageable(damageable, damageable.gameObject, registerAllChildObjects); } public void RegisterDamageable(Damageable damageable, GameObject key, bool registerAllChilObjects=false) { UnityEngine.Assertions.Assert.IsNotNull<Damageable>(damageable); UnityEngine.Assertions.Assert.IsFalse(_trackedDamageables.ContainsKey(key)); _trackedDamageables.Add(key, damageable); if(registerAllChilObjects) { foreach(Transform t in key.transform) { RegisterDamageable(damageable, t.gameObject); } } } Just for clarity here are the method definitions only: Code (CSharp): public void RegisterDamageable(Damageable damageable, bool registerAllChildObjects = false) public void RegisterDamageable(Damageable damageable, GameObject key, bool registerAllChilObjects=false) Clearly, they have different method signatures. However, The call in the foreach loop in the second method is generating an ambiguous call - " Assets/Main/Scripts/DamageDispatcher.cs(45,21): error CS0121: The call is ambiguous between the following methods or properties: `DamageDispatcher.RegisterDamageable(Damageable, bool)' and `DamageDispatcher.RegisterDamageable(Damageable, UnityEngine.GameObject, bool)'" Why? Clearly I am passing a GameObject in to the method? There is only one version of the method that accepts a GameObject parameter. To me it seems like GameObject is being treated as a boolean . Which would cause the compiler confusion. If this is true, why? Is there some funky operator overloading going on in GameObject? and if so for what purpose? By the way, I know I can force the correct method by just passing in a false third parameter and I have fixed it by doing that but I dont like not fully understanding why.
I seem to remember coming across this before, if I remember correctly, it has to do with overloads and setting defaults for arguements not playing well together. Try it without the setting the defaults, instead overloading them. Something like this: Code (CSharp): public void RegisterDamageable(Damageable damageable) { RegisterDamageable(damageable, damageable.gameObject, false); } public void RegisterDamageable(Damageable damageable, bool registerAllChildObjects) { RegisterDamageable(damageable, damageable.gameObject, registerAllChildObjects); } public void RegisterDamageable(Damageable damageable, GameObject key) { RegisterDamageable(damageable, key, false); } public void RegisterDamageable(Damageable damageable, GameObject key, bool registerAllChilObjects) { [...] }
GameObject has a bool operator that's probably causing this. It can be used to test if it is not null and not destroyed.
This is because UnityEngine.Object (which GameObject inherits from) has an implicit bool conversion. Meaning it's interchangable with booleans. So when the compiler comes to the method, it sees that the GameObject satisfies BOTH methods (either as being passed as a GameObject, or converted to a bool). Thusly the call is ambiguous, two methods are valid.