具有两个不相等(唯一)类型的泛型类

use*_*939 7 c# generics constraints

是否可以实现一个约束为两个唯一通用参数的类?

如果不是,那是因为它没有实现,还是因为语言结构(继承)是不可能的?

我想要一些形式:

class BidirectionalMap<T1,T2> where T1 != T2
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

我正在实现双向字典.这主要是好奇心问题,而不是需要.


从评论中复述:

  1. 丹:"如果不满足这种约束,会有什么负面影响?"

  2. 我:"然后用户可以使用map [t1]和map [t2]进行索引.如果它们是相同的类型,则没有任何区别,也没有任何意义."

  3. Dan:编译器实际上允许[两个泛型类型参数来定义不同的方法重载],所以我很好奇; 它是否随意选择其中一种方法来调用?

Dan*_*ant 6

扩展示例以突出问题:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以答案是,即使您不能指定约束 T1 != T2,也没关系,因为只要您尝试执行违反隐式约束的操作,编译器就会失败。它仍然会在编译时捕获失败,因此您可以不受惩罚地使用这些重载。这有点奇怪,因为您可以创建映射的实例(甚至可以编写适当操作映射的 IL 代码),但是 C# 编译器不会让您通过任意解决不明确的重载来造成严重破坏。


一方面要注意的是,如果您不小心,这种重载可能会导致一些奇怪的行为。如果你有一个BidirectionalMap<Animal, Cat>and Cat : Animal ,考虑一下这段代码会发生什么:

Animal animal = new Cat();
map.Remove(animal);
Run Code Online (Sandbox Code Playgroud)

这将调用带 Animal 的重载,因此它会尝试删除一个键,即使您可能打算删除值 Cat。这是一个有点人为的情况,但是当由于方法重载而发生非常不同的行为时,这足以保证谨慎。在这种情况下,如果您只是为方法赋予不同的名称,以反映它们不同的行为(例如,RemoveKey 和 RemoveValue),则可能更易于阅读和维护。