locked
Generic method and overload resolution RRS feed

  • Question

  • Given the following two methods:

    public static void OverloadResolutionProblem(IComparable c) { }
    public static void OverloadResolutionProblem<T>(T c) where T : IConvertible { }

    and the following call:

    OverloadResolutionProblem(new Guid());

    Why does the compiler complain?

    The generic method should not be considered as an applicable method since Guid doesn't satisfy the constraint, leaving only the non-generic method in the set of candidate methods.

    Tuesday, June 22, 2010 4:26 PM

Answers

  • Unfortunately, constraints are not considered when doing generic overload resolution. So it's sees the generic overload as a better match than the one which uses the interface.
    http://blog.voidnish.com
    Tuesday, June 22, 2010 4:36 PM
    Moderator
  • The compiler doesn't take constraints into account during overload resolution, so it deems that T is the best match because it can infer a Guid. Generic methods are less specific than non-generic methods for the purposes of overload resolution, but that only matters if the type arguments of both methods are the same after inference. In this case, T is more specific than IComparable.
    Tuesday, June 22, 2010 4:37 PM

All replies

  • Unfortunately, constraints are not considered when doing generic overload resolution. So it's sees the generic overload as a better match than the one which uses the interface.
    http://blog.voidnish.com
    Tuesday, June 22, 2010 4:36 PM
    Moderator
  • The compiler doesn't take constraints into account during overload resolution, so it deems that T is the best match because it can infer a Guid. Generic methods are less specific than non-generic methods for the purposes of overload resolution, but that only matters if the type arguments of both methods are the same after inference. In this case, T is more specific than IComparable.
    Tuesday, June 22, 2010 4:37 PM
  • I agree.  You can observe this behavior for yourself.  Create a generic version of the plain method.....

        public static void OverloadResolutionProblem(IComparable c)
        {
        }
    
        public static void OverloadResolutionProblem(IConvertible c)
        {
        }
    
        public static void OverloadResolutionProblem<U>(U c) where U : IComparable
        {
        }
    
        public static void OverloadResolutionProblem<T>(T c) where T : IConvertible
        {
        }

    The compiler will complain that there are two methods with the same signature.  I believe that Generics compile to the most base class possible, System.Object.  The last two methods would be percieved as having the same signature.  I have always encountered issues mixing generics with non-generics, too.

    Rudy  =8^D


    Mark the best replies as answers. "Fooling computers since 1971."
    Tuesday, June 22, 2010 10:14 PM
    Moderator
  • The compiler doesn't take constraints into account during overload resolution, so it deems that T is the best match because it can infer a Guid. Generic methods are less specific than non-generic methods for the purposes of overload resolution, but that only matters if the type arguments of both methods are the same after inference. In this case, T is more specific than IComparable.

    The C# specification says that constraints are considered before overload resolution, when the set of candidate methods is constituted. The generic method should not be looked at when searching the best match.

    Wednesday, June 23, 2010 12:04 AM
  • I agree.  You can observe this behavior for yourself.  Create a generic version of the plain method.....

      public static void OverloadResolutionProblem<U>(U c) where U : IComparable
      {
      }
    
      public static void OverloadResolutionProblem<T>(T c) where T : IConvertible
      {
      }
    

    The compiler will complain that there are two methods with the same signature.  I believe that Generics compile to the most base class possible, System.Object.  The last two methods would be percieved as having the same signature.  I have always encountered issues mixing generics with non-generics, too.

    Rudy  =8^D


    Mark the best replies as answers. "Fooling computers since 1971."

    Generics don't "compile to the most base class possible". They compile to generic methods. Constraints are not part of the signature.
    Wednesday, June 23, 2010 12:09 AM
  • The C# specification says that constraints are considered before overload resolution, when the set of candidate methods is constituted. The generic method should not be looked at when searching the best match.


    Louis,

    No, it does not say that. This following blog entry should elucidate things better:

    http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx


    http://blog.voidnish.com
    Wednesday, June 23, 2010 12:09 PM
    Moderator
  • "all constructed types in the parameter list of F satisfy their constraints"

    I understand now. What is checked is the constraints on the arguments of the method, not the constraints on the type parameters.

    That means you cannot use constraints to choose which method is called. If the constraint is not satisfied, it's a compiler error even if another method is a valid candidate. If the constraint is satisfied, the non-generic method will be chosen only in the case of an exact argument type match.

    Wednesday, June 23, 2010 1:39 PM
  • Yes, so while you may disagree with the behavior, it's not a compiler bug. It would be more accurate to say that the C# language design decision is not very agreeable to you. Again, that's a very subjective thing.
    http://blog.voidnish.com
    Wednesday, June 23, 2010 4:06 PM
    Moderator
  • I don't have a problem with the design decision. I was just annoyed to see difference between the specification and the compiler behavior. Now that I see I was wrong, that's ok with me. It prevents making unintended calls to the non-generic method. If I want to call the non-generic method, I just need to cast the argument to the expected type:

     

    OverloadResolutionProblem((IComparable)new Guid());

     

    Thursday, June 24, 2010 12:46 AM