C# 泛型方法解析失败,出现不明确的调用错误
C# generic method resolution fails with an ambiguous call error
假设我定义了两个不相关的类型和两个具有相同签名但类型过滤器不同的扩展方法:
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 在 class 层次结构上工作:
new Foo()
.Frob()
.Brob()
泛型类型参数的约束不是方法签名的一部分。从分辨率的角度来看,这两种方法本质上是相同的;当编译器尝试解析调用时,它会看到两个有效方法,但无法选择更好的方法,因此该调用被标记为不明确。
您可以阅读有关此问题的更多信息here。
实际上,总体目标(根据你的描述和我的实践和观点)是更简洁地表示 classes 的“相似”扩展集。 “相似性”部分可能是这些 classes 的名称是相当长的多部分驼峰标识符,甚至在第一部分并不总是不同。
所以,使用泛型只有在class继承[=20=的情况下才有用].对于不可继承的 classes 解决方案是使用短 class aliases.
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();
假设我定义了两个不相关的类型和两个具有相同签名但类型过滤器不同的扩展方法:
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 在 class 层次结构上工作:
new Foo()
.Frob()
.Brob()
泛型类型参数的约束不是方法签名的一部分。从分辨率的角度来看,这两种方法本质上是相同的;当编译器尝试解析调用时,它会看到两个有效方法,但无法选择更好的方法,因此该调用被标记为不明确。
您可以阅读有关此问题的更多信息here。
实际上,总体目标(根据你的描述和我的实践和观点)是更简洁地表示 classes 的“相似”扩展集。 “相似性”部分可能是这些 classes 的名称是相当长的多部分驼峰标识符,甚至在第一部分并不总是不同。
所以,使用泛型只有在class继承[=20=的情况下才有用].对于不可继承的 classes 解决方案是使用短 class aliases.
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();