Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

C# Compiler "The call is ambiguous..." error when using Visual studio for mac

Discussion in 'Experimental Scripting Previews' started by M_R, Aug 9, 2017.

  1. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    Hi,
    I was trying out Visual Studio for mac. I have code of this form in my projects:
    Code (CSharp):
    1. using System;
    2.  
    3. public class MyClass
    4.     {
    5.         public MyClass ()
    6.         {
    7.             Outer (Inner);
    8.         }
    9.  
    10.         void Inner () {  }
    11.  
    12.         void Outer(Action inner){inner ();}
    13.         void Outer(Func<MyClass> inner){inner ();}
    14.     }
    that compiles and runs fine with Monodevelop-Unity from 5.6.2 but gives this error when compiled with VS:
    Code (CSharp):
    1. /Users/***/Projects/TestOverload/TestOverload/MyClass.cs(4,4): Error CS0121: The call is ambiguous between the following methods or properties: 'MyClass.Outer(Action)' and 'MyClass.Outer(Func<MyClass>)' (CS0121) (TestOverload)
    I also tried with .net 4.6 runtime in Unity 2017.1 and it compiles in both monodevelop and unity

    Is this a breaking change that we should be aware of when you will upgrade to Roslyn?
     
  2. FMark92

    FMark92

    Joined:
    May 18, 2017
    Posts:
    1,243
    I'm getting the same error in VS2017 on windows.

    What is the expected outcome here? Am I correct in thinking that the correct choice for compiler would be
    Code (CSharp):
    1. void Outer(Action inner) { inner(); }
    ?

    Also why are you compiling Unity solution with VS? You have Unity for that.
     
  3. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    We'll keep an eye on it for the Roslyn upgrade. Usually Roslyn is more correct than the Mono C# compiler (mcs) in cases like this, so it might be a valid error from Roslyn.
     
  4. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    error CS0121: The call is ambiguous between the following methods or properties: 'MyClass.Outer(Action)' and 'MyClass.Outer(Func<MyClass>)'

    C# 7.1, Roslyn 2.3.1.61919
     
  5. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    currently mono picks the expected overload ( void Outer (Action inner) { inner (); } ) and compiles.

    some more cases:
    1) if Inner is " MyClass Inner () { ... } " both mono and VS compile (picking the Func<> overload)
    2) if we add a third overload " void Outer (Func<int> inner) { inner (); } " mono still compile, but roslyn throws an ambiguity between " void Outer (Func<MyClass> inner) " and " void Outer (Func<int> inner) "
    2.1) void Inner() {} still causes ambiguity between the first 2 overload declared.

    point 1 seems a little strange. why some candidates can be picked but others can't?

    1) I also compile directly in the IDE (via cmd-B hotkey) when writing code going back to Unity only when I am done)
    2) I also have separate DLLs for stuff that doesn't depend on Unity
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Shouldn't this obviously resolve to the Action variant? The delegate Action matches the signature of Inner, while the delegate Func<MyClass> clearly doesn't.

    If we comment out the Action variant, the code doesn't compile with:
    "void MyClass.Inner() has the wrong return type

    Expected a method with MyClass Inner() signature"

    When there's two overloads, but only one of them would compile if it was picked, that one should be the one picked, right?
     
  7. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    I found this issue on roslyn, but it seems related to optional parameters.
    indeed, adding optional parameters changes the behaviour:
    - adding an optional parameter to the Func overload causes roslyn to pick the correct (Action) overload
    - adding an optional parameter to the Action overload causes roslyn to pick the Func overload, then it fails with "wrong return type"
    - adding an optional parameter to both retains the ambiguity error.

    - using a non-void returning Inner compiles every case, always picking the correct overload

    - MonoDevelop compiles all 8 cases correctly

    source with all cases:
    Code (CSharp):
    1. using System;
    2.  
    3. namespace TestOverload
    4. {
    5.     public class MyClass
    6.     {
    7.         public MyClass ()
    8.         {
    9.             Outer (Inner); // CS0121 (ambiguous call)
    10.             Outer (Inner2); // compiles
    11.  
    12.             Outer2 (Inner); // compiles
    13.             Outer2 (Inner2); // compiles
    14.  
    15.             Outer3 (Inner); // CS0407 (wrong return type)
    16.             Outer3 (Inner2); // compiles
    17.  
    18.             Outer4 (Inner); // CS0121 (ambiguous call)
    19.             Outer4 (Inner2); // compiles
    20.         }
    21.  
    22.         void Inner () {  }
    23.         MyClass Inner2 () { return null; }
    24.  
    25.         void Outer(Action inner){inner ();}
    26.         void Outer(Func<MyClass> inner){inner ();}
    27.  
    28.         void Outer2(Action inner){inner ();}
    29.         void Outer2(Func<MyClass> inner, bool opt = false){inner ();}
    30.  
    31.         void Outer3(Action inner, bool opt = false){inner ();}
    32.         void Outer3(Func<MyClass> inner){inner ();}
    33.  
    34.         void Outer4 (Action inner, bool opt = false) { inner (); }
    35.         void Outer4 (Func<MyClass> inner, bool opt = false) { inner (); }
    36.     }
    37. }