C#泛型方法解析失败,暧昧的呼叫错误

问题描述:

假设我已经定义了两个不相关的类型,并具有相同签名的两个扩展方法,但不同类型的过滤器:C#泛型方法解析失败,暧昧的呼叫错误

public class Foo {} 
public class Bar {} 

public static class FooExtensions 
{ 
    public static TFoo Frob<TFoo>(this TFoo foo) where TFoo : Foo { } 
    public static TFoo Brob<TFoo>(this TFoo foo) where TFoo : Foo { } 
} 

public static class BarExtensions 
{ 
    public static TBar Frob<TBar>(this TBar bar) where TBar : Bar { } 
} 

后来,当我写new Foo().Frob();我得到一个错误

error CS0121: The call is ambiguous between the following methods or properties: 'FooExtensions.Frob<TFoo>(TFoo)' and 'BarExtensions.Frob<TBar>(TBar)'

有人可以解释为什么这会失败,如何避免它?

编辑:这发生在VS2015更新3和VS2017 RC。

EDIT2:这里的想法是要有一个类层次结构的工作原理流畅API:

new Foo() 
    .Frob() 
    .Brob() 
+0

接受的答案是正确的;我注意到你在这里做的是一个不好的习惯。请不要通过扩展对象或扩展泛型类型T来扩展* everything *的扩展方法。几乎总是有更好的设计。在这种情况下,为什么不简单地扩展Foo和Bar?有什么令人信服的好处,使这些通用? –

+0

@EricLippert,我已经简化了这个场景。实际上,扩展方法返回'TFoo'。这里的想法是让流利的API方法在类层次结构上工作。所以我可以写'new Foo()。Frob()。Grob()。Blob();'。当我有两个独立类型时,问题就出现了,但扩展方法的顺序相同。 –

泛型类型参数的约束是不是方法签名的一部分。从分辨率的角度来看,这两种方法基本相同;当编译器尝试解析调用时,它会看到两个有效的方法,并且无法选择更好的方法,因此调用会被标记为不明确。

您可以阅读更多关于此问题here

+0

感谢您的链接;我自己不能说得更好。 –

+3

@EricLippert非常感谢你,很难夸大我对语言学习的多少,以及一般的编程知识,阅读你的博客。 – InBetween