Search Unity

How is this call ambiguous [C#]

Discussion in 'Scripting' started by Korno, Feb 12, 2016.

  1. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    Ok, I have two methods, what they do is not really important, shown below:

    Code (CSharp):
    1.  public void RegisterDamageable(Damageable damageable, bool registerAllChildObjects = false)
    2.         {
    3.             RegisterDamageable(damageable, damageable.gameObject, registerAllChildObjects);
    4.         }
    5.  
    6. public void RegisterDamageable(Damageable damageable, GameObject key, bool registerAllChilObjects=false)
    7.         {
    8.             UnityEngine.Assertions.Assert.IsNotNull<Damageable>(damageable);
    9.              UnityEngine.Assertions.Assert.IsFalse(_trackedDamageables.ContainsKey(key));
    10.             _trackedDamageables.Add(key, damageable);
    11.             if(registerAllChilObjects)
    12.             {
    13.                 foreach(Transform t in key.transform)
    14.                 {
    15.                     RegisterDamageable(damageable, t.gameObject);
    16.                 }
    17.             }
    18.         }
    Just for clarity here are the method definitions only:

    Code (CSharp):
    1.  public void RegisterDamageable(Damageable damageable, bool registerAllChildObjects = false)
    2.  
    3.  public void RegisterDamageable(Damageable damageable, GameObject key, bool registerAllChilObjects=false)
    4.  
    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.
     
  2. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,052
    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):
    1.  
    2. public void RegisterDamageable(Damageable damageable)
    3. {
    4.     RegisterDamageable(damageable, damageable.gameObject, false);
    5. }
    6.  
    7. public void RegisterDamageable(Damageable damageable, bool registerAllChildObjects)
    8. {
    9.     RegisterDamageable(damageable, damageable.gameObject, registerAllChildObjects);
    10. }
    11.  
    12. public void RegisterDamageable(Damageable damageable, GameObject key)
    13. {
    14.     RegisterDamageable(damageable, key, false);
    15. }
    16.  
    17. public void RegisterDamageable(Damageable damageable, GameObject key, bool registerAllChilObjects)
    18. {
    19.     [...]
    20. }
     
  3. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    GameObject has a bool operator that's probably causing this. It can be used to test if it is not null and not destroyed.
     
    Kiwasi and Korno like this.
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    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.
     
  5. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    I guessed so, thanks for confirming my suspicion.