Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有两个不相等(唯一)类型的泛型类_C#_Generics_Constraints - Fatal编程技术网

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

C# 具有两个不相等(唯一)类型的泛型类,c#,generics,constraints,C#,Generics,Constraints,是否可以实现一个约束为两个唯一泛型参数的类 如果不是,是因为它没有实现,还是因为考虑到语言结构(继承),它是不可能实现的 我想要以下形式的东西: class BidirectionalMap<T1,T2> where T1 != T2 { ... } 类双向映射,其中T1!=T2 { ... } 我正在实施一项计划。这主要是好奇心的问题,而不是需要 从评论中转述: 丹:“如果不满足这一约束,会产生什么负面后果?” Me:“然后用户可以使用map[t1]和map[t2]进行索

是否可以实现一个约束为两个唯一泛型参数的类

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

我想要以下形式的东西:

class BidirectionalMap<T1,T2> where T1 != T2
{
  ...
}
类双向映射,其中T1!=T2
{
...
}
我正在实施一项计划。这主要是好奇心的问题,而不是需要


从评论中转述:

  • 丹:“如果不满足这一约束,会产生什么负面后果?”

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

  • Dan:编译器实际上允许[两个泛型类型参数定义不同的方法重载],所以我很好奇它是否任意选择要调用的方法之一?


  • 类型约束似乎用词不当。虽然它们不知道类型参数是什么,但目的是让编译器知道类型可以使用哪些操作。

    如果愿意,可以使用一个约束,其中T1和T2都派生自单独的具体基类,但我认为这不是您想要的。

    如果不对类型本身施加任何其他限制,就没有有效的方法来实现这一点。正如其他人所指出的,您可以对这两种类型从两个不同的基类派生的约束进行约束,但从设计的角度来看,这可能不是很好


    编辑为添加:未实现此功能的原因很可能是因为Microsoft没有人认为在编译时强制执行类似的功能是必要的,这与其他约束不同,这些约束与如何实际使用指定类型的变量有关。正如一些评论者所指出的,您当然可以在运行时强制执行此操作。

    该不等式不会帮助编译器捕获错误。当您在类型参数上指定约束时,您是在告诉编译器这种类型的变量将始终支持某个接口或以某种方式运行。每种方法都允许编译器验证类似于“此方法将出现,以便可以在T上调用它”的内容


    类型参数的不平等性更像是验证方法参数不是null。它是程序逻辑的一部分,而不是它的类型安全性。

    我不完全确定为什么这是一个理想的编译时检查。本质上,可以通过装箱键或值来旁路条件,从而使编译时检查无效

    需要进行一些考虑以确定。。。我试图防止哪些错误

    如果您只是阻止一个懒惰的同事不阅读文档,那么添加一个只进行调试的检查并抛出一个异常。通过这种方式,可以删除释放代码的检查,例如

    #if Debug
    
    if (T1 is T2 || T2 is T1)
    {
        throw new ArguementException(...);
    }
    
    #endif
    

    如果您试图阻止恶意的人以非预期的方式使用您的库,那么可能需要进行运行时检查,否则很容易将键或值框起来

    否,不能将相等(或不相等)用作约束。简单地说,平等不是一种约束,而是一种条件。您应该在构造函数中测试类型的相等或不相等等条件,并引发相应的异常。

    展开示例以突出显示问题:

    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");
        }
    }
    

    这将调用获取Animal的重载,因此它将尝试删除一个键,即使您可能打算删除值Cat。这在某种程度上是一种人为的情况,但当方法重载导致出现非常不同的行为时,这足以保证谨慎。在这种情况下,如果只为方法指定不同的名称,反映它们的不同行为(比如RemoveKey和RemoveValue),则可能更易于阅读和维护。

    您可以始终在构造函数中抛出一个
    new ShouldbeCompleTimeError()
    。:-)可能是因为它没有意义,它们是泛型,不应该被类型“约束”。出于好奇,如果不满足这个约束,会有什么负面后果?同一集合中的对象之间的映射是一个非常常见的要求。@user664939,我深入研究了一下,编译器允许您使用匹配的重载编译一个类,但当您尝试调用该方法时(调用错误不明确),它会失败它似乎允许您定义一个编译并可引用的泛型专门化,但C#编译器无法发出调用该方法的代码(可以发出IL来调用这两个方法中的一个,但编译器在T1==T2时无法分辨差异。)@DaveC:如果您有
    类映射{void Remove(T1 t){…}void Remove(T2 t){…}
    ,调用
    新映射()时将运行哪一个。Remove(“人为示例”)
    ?出色的根答案!错误文本:`调用在以下方法或属性之间不明确:BidirectionalMap.this[t]”和“BidirectionalMap.this[K]”“您也可以将此检查放入泛型类型的静态构造函数中,因此它只运行一次。(顺便说一下,您的检查不会编译,因为
    is
    运算符的左侧接受对象引用,而不是类型名称。您希望
    if(typeof(T1)==typeof(t2)
    Animal animal = new Cat();
    map.Remove(animal);