简体   繁体   中英

Generic and non-generic method overload rules with type inference

Given the following two overloaded method signatures:

public B DoSomething<A,B>(A objOne, B objTwo)
public object DoSomething(object objOne, Type objType);

I would expect that calling this would call the second signature, but it does not:

var obj = new SomeType();
var type = typeof(SomeOtherType);

DoSomething(obj, type);

It seems to me that looking at the spec, the second overload is more applicable (has one exact type and lesser arity). But, it does not get called. Instead, the first overload is called with A as the type object and B as the type Type . Why is that and is there a way to call this method aside from either renaming the method or using named parameters?

EDIT:

Here are the parts of the spec I'm referring to in 7.5.3.2:

In case the parameter type sequences {P1, P2, …, PN} and {Q1, Q2, …, QN} are equivalent (ie each Pi has an identity conversion to the corresponding Qi), the following tie-breaking rules are applied, in order, to determine the better function member.

  • If MP is a non-generic method and MQ is a generic method, then MP is better than MQ.
  • ...
  • Otherwise, if MP has more specific parameter types than MQ, then MP is better than MQ. Let {R1, R2, …, RN} and {S1, S2, …, SN} represent the uninstantiated and unexpanded parameter types of MP and MQ. MP's parameter types are more specific than MQ's if, for each parameter, RX is not less specific than SX, and, for at least one parameter, RX is more specific than SX:
    • A type parameter is less specific than a non-type parameter.
    • ...

After your edit here is methods for compiler to choose between

DoSomething<SomeType,Type>(SomeType o, Type t)
DoSomething(object o,Type t);

As specification says about picking better function member:

Given an argument list A with a set of argument expressions { E1, E2, ..., EN } and two applicable function members MP and MQ with parameter types { P1, P2, ..., PN } and { Q1, Q2, ..., QN }, MP is defined to be a better function member than MQ if
• for at least one argument, the conversion from EX to PX is better than the conversion from EX to QX.

Generic method have better conversion from SomeType to SomeType than non-generic's method conversion from SomeType to object . If non-generic method would be defined as

DoSomething(SomeType o, Type t);

then there would not be any arguments with better conversion, and you'll fall into case:

In case the parameter type sequences {P1, P2, …, PN} and {Q1, Q2, …, QN} are equivalent

Where first rule would pick non-generic method:

• If MP is a non-generic method and MQ is a generic method, then MP is better than MQ.


NOTE: Before you edited question, there was first argument of type object , and generic method was

DoSomething<object,Type>(object o, Type t)

And again, parameter sequences are equivalent in this case, and non-generic method is picked.

In my test, I was able to use a cast to get the resolution you want. DoSomething((object)"1234", typeof(string));

调用DoSomething<object, SomeType>(obj, type)();

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