简体   繁体   中英

Calling the wrong overload for generic method

I have two generic methods which are very similar. The idea is that one can be called with an explicit return type, whereas the other infers that the return type is the same as the obj provided.

The first method would be called like: RestResponse response = myCat.Put<RestResponse>()

//Perform a PUT on the current resource, returning the server response deserialized to a new object of the specified type.</summary>
//<typeparam name="T">The expected type of the resource post response. Use 'IRestResponse' to skip deserializing the request.</typeparam>
public static T Put<T>(this APIResource obj, List<Parameter> parameters = null)
{
    if (parameters == null) parameters = new List<Parameter>();
    parameters.Add(new Parameter() { Value = obj, Type = ParameterType.RequestBody });
    return RequestHelper<T>(obj.collection_name + "/" + obj.id, Method.PUT, parameters);
}

And the automatic one is called as such Cat response = myCat.Put();

//<typeparam name="O">(Automatically Inferred) The type of the current resource, which is also the expected type of the resource request response.</typeparam>
public static O Put<O>(this O obj, List<Parameter> parameters = null) 
     where O : APIResource 
{ return obj.Put<O>(parameters); } //I want to call the first method here.

Now I can see how these definitions are ambiguous with restpect to eachother. The weird thing is that there's no compile errors, but at run time, I get a stack overflow because the second method just calls itself.

Is there a way I can get the second method to call the first without changing the name of either method?

When deciding the "betterness" of two methods (which is what is done when a method call matches multiple signatures) the method that is defined "closer" to the call point is preferred.

Two of the more common examples:

  1. If one method is defined in that same type and another isn't, the one in that type wins.

  2. If one method is in the same namespace and another isn't, then the one in the same namespace wins.

One way of resolving the ambiguity is to not leverage the fact that it is an extension method; call it as if it weren't (it can still be an extension method though, for use by external callers).

public static O Put<O>(this O obj, List<Parameter> parameters = null) 
     where O : APIResource 
{ return OtherPutClass.Put<O>(obj, parameters); }

Have you tried explicitly casting to the correct type?

It would seem that something like:

public static O Put<out O>( this O obj , List<Parameter> parameters = null ) where O:APIResource
{
  return ((APIResource)obj).Put<O>(parameters) ;  //I want to call the first method here.
}

or

public static O Put<out O>( this O obj , List<Parameter> parameters = null ) where O:APIResource
{
  return .Put<O>( (APIResource)obj , parameters) ;  //I want to call the first method here.
}

we get you what you want.

However, the fact that the type system is confused with respect to your intent might be an indication that somebody trying to fix a bug down the line is also going to be confused.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM