Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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# 平等比较公司<;T>;。默认值为';我不够聪明_C#_.net_Enums_Equals_Iequalitycomparer - Fatal编程技术网

C# 平等比较公司<;T>;。默认值为';我不够聪明

C# 平等比较公司<;T>;。默认值为';我不够聪明,c#,.net,enums,equals,iequalitycomparer,C#,.net,Enums,Equals,Iequalitycomparer,我正在阅读EqualityComparer.Default的源代码,发现它并不那么聪明。以下是一个例子: enum MyEnum : int { A, B } EqualityComparer<MyEnum>.Default.Equals(MyEnum.A, MyEnum.B) //is as fast as EqualityComparer<int>.Default.Equals(0, 1) enum AnotherEnum : long { A = 1L, B =

我正在阅读
EqualityComparer.Default
的源代码,发现它并不那么聪明。以下是一个例子:

enum MyEnum : int { A, B }
EqualityComparer<MyEnum>.Default.Equals(MyEnum.A, MyEnum.B)
//is as fast as 
EqualityComparer<int>.Default.Equals(0, 1)

enum AnotherEnum : long { A = 1L, B = 2L }
//is 8x slower than
EqualityComparer<long>.Default.Equals(1L, 2L)
上面两个是聪明的,但是
EqualityComparer.Default
是不吉利的,从方法中我们可以看到它最终得到了一个
ObjectEqualityComparer()
,其
Equals
方法可能如下所示:

public static bool Equals(int x, int y)
{
    return x == y;  //or return x.Equals(y); here 
                    //I'm not sure, but neither causes boxing
}

public static bool Equals(MyEnum x, MyEnum y)
{
    return x == y;  //it's impossible to use x.Equals(y) here 
                    //because that causes boxing
}
public static bool Equals(AnotherEnum x, AnotherEnum y)
{
    return x.Equals(y);   //too bad, the Equals method is from System.Object
                       //and it's not override, boxing here!
                       //that's why it's so slow
}

我认为这个条件
Enum.GetUnderlyingType(c)=typeof(int)
是没有意义的,如果枚举的基础类型是int类型,那么该方法可以将int的默认比较器转换为该枚举。但是为什么不能基于long的枚举呢?我想没那么难吧?有什么特别的原因吗?对于enum来说,构造一个类似于
x==y
的比较器并不难,对吧?为什么它最终为枚举提供了一个缓慢的
ObjectEqualityComparer
(即使它工作正常)?

我认为,对于负责添加此功能的团队来说,根本没有令人信服的理由。所有特性都有实现成本,其中包括(除其他外)记录、编码和测试的时间

有两个令人信服的原因,为什么到目前为止,这个特定的功能还没有被选中(并且可能永远不会被选中):

  • 它只适用于非常狭窄的场景(比较
    枚举
    int
    以外的内容支持,并在一些内部循环中执行)
  • 如果它给您带来问题,有一个非常简单且可发现的解决方案(编写您自己的比较器)

是的,我认为该场景的狭隘性是关键所在。如果他们考虑了长,他们也应该包括byte、short等……但是,如果他们努力添加条件,那一定是有原因的。@FrantišekŽiačik:覆盖99%的情况将是一个原因:)我没有说清楚。如果我引用Danny Chen,“我认为这个条件
Enum.getUnderfullyingType(c)=typeof(int)
是毫无意义的,如果这是真的,那么添加它会将覆盖率从100%缩小到99%。所以他们应该有一个很好的理由,不是吗。啊,我又看了一遍代码,现在我明白了,他们必须使用一个具体的
EnumEqualityComparer
,这就是原因。顺便说一句,你可以编写自己的代码,其中有没错。但我还没有找到一种没有代码生成或C++/CLI的方法。我找不到一种方法,即使使用不安全的{}允许通过C#中的void*和泛型类型重新解释强制转换。我刚刚在GitHub上发布了一个小库,它可以让您使默认的相等比较器尽可能聪明:
public static bool Equals(AnotherEnum x, AnotherEnum y)
{
    return x.Equals(y);   //too bad, the Equals method is from System.Object
                       //and it's not override, boxing here!
                       //that's why it's so slow
}