扩大的例子突出问题:
public class BidirectionalMap<T1,T2>
{
public void Remove(T1 item) {}
public void Remove(T2 item) {}
public static void Test()
{
//This line compiles
var possiblyBad = new BidirectionalMap<string, string>();
//This causes the compiler to fail with an ambiguous invocation
possiblyBad.Remove("Something");
}
}
因此,答案是,即使你不能指定约束T1 = T2,也不要紧,因为编译器只要你试图做一些违反隐含约束的事情就会失败。它仍然在编译时捕获失败,所以你可以使用这些重载而不受惩罚。这有点奇怪,因为你可以创建一个地图实例(甚至可以编写IL代码来适当地操作地图),但C#编译器不会让你通过任意解决模糊的重载而造成破坏。
一方面要注意的是,如果你不小心,这种重载可能会导致一些奇怪的行为。如果你有一个BidirectionalMap<Animal, Cat>
和猫:动物,可以考虑将与此代码发生的事情:
Animal animal = new Cat();
map.Remove(animal);
这将调用了一个动物的过载,所以它会尝试删除键,即使你可能已经打算删除值Cat。这是一个有些人为的情况,但是当由于方法重载而出现非常不同的行为时,请谨慎行事。在这种情况下,如果您只是给方法不同的名称,反映它们的不同行为(比如RemoveKey和RemoveValue,假设),则读取和维护可能会更容易。
您可以在构造函数中始终抛出一个'ShouldBeBeCompileTimeError()' 。 :-) – foson
可能是因为它没有意义,它们是泛型,不应该被类型“约束”。 – GriffinHeart
出于好奇,如果不满足这个约束,会有什么负面影响?来自同一组的对象之间的映射是非常普遍的要求。 –