hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

Resolving overload conflict

Last post 05-19-2008, 13:25 by olivers. 4 replies.
Sort Posts: Previous Next
  •  05-16-2008, 2:44 5919

    Resolving overload conflict

    I have a scenario where F# can't decide which overload of a method (function in a class) to call. Basically the problem is that I have two overloads in a C# class, one of them with explicitly typed parameters, the other one with generic parameters. I've done some simplified tests which didn't show the same problem, but I managed to create a basic example that reproduces the issue. There seems to be something relevant about the precise implementation of the methods that makes this come up.
    This is the class I have in C#:

        public class BaseClass {
            public bool SetPropertyValue(string propertyName, ref int property, int newValue) {
                return SetEquatablePropertyValue(propertyName, ref property, newValue);
            }

            private bool SetEquatablePropertyValue<T>(string propertyName, ref T property, T newValue) where T : IEquatable<T> {
                T oldValue = property;
                if (oldValue.Equals(newValue))
                    return false;
                property = newValue;
               
                // do other stuff, like change notification

                return true;
            }

            public bool SetPropertyValue<T>(string propertyName, ref T property, T newValue) {
                // same as above, but using a more complex algorithm for equality checking
                return true;
            }
        }

    And this is the F# code I'm trying to use:

    type DerivedClass =
        inherit BaseClass as base
        new() = { inherit BaseClass(); var = 0 }
       
        val mutable private var: int
        member public x.Var
            with get() = x.var
            and set(v) = base.SetPropertyValue("Var", ref x.var, v) |> ignore

    let c = new DerivedClass()
    c.Var <- 42

    When I try to compile this, I get the following error message:

    error FS0041: The method 'SetPropertyValue' is overloaded. Possible matches are shown below (or in the Error List window).

    Possible overload: 'BaseClass.SetPropertyValue(string propertyName, int byref property, int newValue) : bool'.

    Possible overload: 'BaseClass.SetPropertyValue<'T>(string propertyName, 'T byref property, 'T newValue) : bool'.


    Why does this problem come up with the precise C# class I have? And how do I resolve that conflict?

    Thanks
    Oliver
  •  05-16-2008, 12:57 5931 in reply to 5919

    Re: Resolving overload conflict

    Because int is also a T, it seems this is an ambiguity.

    Out of curiosity, is there a rule in C# that says it always chooses the most specific method when using overloads (I can foresee some problems when defining that "most specific" though...)

    Kurt
  •  05-16-2008, 13:52 5932 in reply to 5931

    Re: Resolving overload conflict

    > Out of curiosity, is there a rule in C# that says it always chooses the most specific method when using overloads

    I think there might be, at least that's what C# does. And F# does it as well - in these examples, the distinction works correctly. In the C# class:

      public void Reply2(string arg1, ref int arg2) {
       Console.WriteLine( "statically typed version");
      }

      public void Reply2<T>(string arg1, ref T arg2) {
       Console.WriteLine( "generic version");
      }

      public void Reply3(int arg1, ref int arg2) {
       Console.WriteLine("statically typed version");
      }

      public void Reply3<T>(T arg1, ref T arg2) {
       Console.WriteLine("generic version");
      }

    And in F#:

    let aval = 10
    testclass.Reply2("blah", ref aval)
    testclass.Reply3(10, ref aval);

    Both of these result in the output "statically typed version".

    I have no idea in which significant way the other example is different from those working cases.

  •  05-18-2008, 1:25 5949 in reply to 5932

    Re: Resolving overload conflict

    olivers:

    I have no idea in which significant way the other example is different from those working cases.



    The fact that you're calling it on a base class may add extra concerns to the mix.

    By the way, in your constructor you are comparing var to zero. I think you mean assigment.

    Kurt
  •  05-19-2008, 13:25 5956 in reply to 5949

    Re: Resolving overload conflict

    Kurt:
    The fact that you're calling it on a base class may add extra concerns to the mix.

    That is something that came to my mind as well, but in tests it doesn't seem to be the reason, since there are enough working cases that use base class methods as well.

    Now, I've found a workaround for this with help from Brian McNamara. It's documented on my blog at http://www.sturmnet.org/blog/archives/2008/05/16/oddities-in-fc-interaction/

    I still regard this a bug really - there doesn't seem to be any explanation for the behavior I'm seeing and Brian hasn't come up with anything either.

    Kurt:
    By the way, in your constructor you are comparing var to zero. I think you mean assigment.

    Surprising as it may seem, that is actually an assignment. For this first-time initialization enforced by the compiler, one has to use = to assign the value, not <-. Weird, isn't it?

    Oliver

View as RSS news feed in XML
Powered by Community Server, by Telligent Systems