C# 具有类型推断的泛型和非泛型方法重载规则

C# 具有类型推断的泛型和非泛型方法重载规则,c#,generics,overloading,C#,Generics,Overloading,给定以下两个重载方法签名: public B DoSomething<A,B>(A objOne, B objTwo) public object DoSomething(object objOne, Type objType); 在我看来,从规范来看,第二个重载更适用(有一个确切的类型和较少的算术)。但是,它没有被调用。相反,调用第一个重载时,A作为类型对象,B作为类型类型。为什么会这样?除了重命名方法或使用命名参数之外,还有没有其他方法调用此方法 编辑: 以下是我在7.5.3.

给定以下两个重载方法签名:

public B DoSomething<A,B>(A objOne, B objTwo)
public object DoSomething(object objOne, Type objType);
在我看来,从规范来看,第二个重载更适用(有一个确切的类型和较少的算术)。但是,它没有被调用。相反,调用第一个重载时,A作为类型
对象
,B作为类型
类型
。为什么会这样?除了重命名方法或使用命名参数之外,还有没有其他方法调用此方法

编辑:

以下是我在7.5.3.2中提到的规范部分:

如果参数类型序列{P1,P2,…,PN}和{Q1,Q2,…,QN}是等价的(即,每个Pi都有一个到相应Qi的标识转换),则应用以下平局打破规则来确定更好的函数成员

  • 如果MP是非泛型方法,而MQ是泛型方法,则MP优于MQ
  • 否则,如果MP具有比MQ更具体的参数类型,则MP优于MQ。设{R1,R2,…,RN}和{S1,S2,…,SN}表示MP和MQ的未实例化和未扩展参数类型。如果对于每个参数,RX不低于SX,并且对于至少一个参数,RX比SX更具体,则MP的参数类型比MQ的更具体:
    • 类型参数不如非类型参数具体

在我的测试中,我能够使用cast获得您想要的分辨率<代码>剂量测量((对象)“1234”,类型(字符串))

呼叫
DoSomething(obj,type)()

编辑后,这里是编译器可以选择的方法

DoSomething<SomeType,Type>(SomeType o, Type t)
DoSomething(object o,Type t);
这样就不会有任何具有更好转换的参数,您将陷入以下情况:

如果参数类型序列{P1,P2,…,PN}和{Q1,Q2…, QN}是等价的

其中第一条规则将选择非泛型方法:

•如果MP是非通用方法,MQ是通用方法,则MP是 比MQ更好


注意:在编辑问题之前,第一个参数的类型是
object
,通用方法是

DoSomething<object,Type>(object o, Type t)
DoSomething(对象o,类型t)

同样,在这种情况下,参数序列是等效的,并且选择了非泛型方法。

您可以为问题添加更多信息吗?我在LinqPad中运行了代码,并使用了非泛型重载。显示的代码(+编译所需的最小数量)没有重现您的问题。请参阅@Jon Skeet的答案。@hunch\u hunch我不确定这里的情况是否完全相同。@anthony pegram抱歉,我不应该将obj作为对象类型。我已经更新了问题,以更准确地反映问题。好吧,如果类型不是object,那么调用泛型重载是完全可以理解的,因为它完全匹配,而非泛型重载不匹配。该强制转换在op的代码中是一个no op;即使没有强制转换,它也会在显示的代码中使用非泛型重载。您必须将第一个参数的编译时类型更改为除
对象
以外的其他类型,才能选择另一个重载。我的建议正确适用于已编辑的问题。它不能正确地应用于原始的未编辑问题。虽然这样做有效,但我希望避免在这里装箱该变量。@Nishmaster,以便该类型是一个结构?如果是这样,您需要使用泛型来避免装箱。在示例代码中,您正在调用一个接受对象参数的方法,因此如果您使用值类型调用,则无法避免装箱。如果使用引用类型调用,则不会发生装箱。我无法做到这一点,因为我不知道编译时的类型。虽然我觉得推断类型应该位于解析树的较低位置,但我明白您对泛型版本的编译时签名的看法。
DoSomething(SomeType o, Type t);
DoSomething<object,Type>(object o, Type t)