假设我已经定义了两个不相关的类型和两个具有相同签名但不同类型过滤器的扩展方法:
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 Update 3和VS2017 RC中。
EDIT2:这里的想法是拥有适用于类层次结构的流畅API:
new Foo()
.Frob()
.Brob()
答案 0 :(得分:11)
泛型类型参数的约束不是方法签名的一部分。从分辨率的角度来看,这两种方法基本相同;当编译器尝试解析调用时,它会看到两个有效的方法,并且无法选择更好的方法,因此调用被标记为不明确。
您可以详细了解此问题here。
答案 1 :(得分:0)
实际上,总体目标(根据您的描述和我的实践和观点)是更简洁地表示类的“类似”扩展集。 “相似之处”部分可能是这些类的名称是相当长的多部分驼峰式标识符,甚至在第一部分并不总是不同。
因此,仅在类继承的情况下使用泛型是好的。对于不可继承的类,解决方案是使用短类别名。
public class Foo0987654321 { }
public class SucFoo0987654321 : Foo0987654321 { }
public class Bar1234567890 { }
namespace NET_Site
{
using B = Bar1234567890;
public static class BarExtensions
{
public static B Frob(this B bar)
{
// ...
return bar;
}
}
}
namespace NET_Site
{
using TFoo = Foo0987654321;
public static class FooExtensions
{
public static TF Frob<TF>(this TF foo)
where TF : TFoo
{
// ...
return foo;
}
public static TF Brob<TF>(this TF foo)
where TF : TFoo
{
// ...
return foo;
}
}
}
new SucFoo0987654321()
.Frob()
.Brob();