比较没有拳击的平等结构

时间:2016-04-24 11:01:59

标签: c# .net equality value-type boxing

我遇到了一个适用于结构(SomeStruct)的扩展方法,并返回该值是否等于default(SomeStruct)(当调用无参数构造函数时)。

public static bool IsDefault<T> (this T value)
    where T : struct
{
    return (!EqualityComparer<T>.Default.Equals(value, default(T)));
}

这让我想知道结构是否被装箱。这完全出于好奇,因为根据具体情况,拳击/传递的价值有利有弊。

假设:

  1. 以下第一种方法是非法的,因为结构不会隐式覆盖相等运算符==/!=
  2. 第二个“出现”以避免拳击。
  3. 第三种方法应该始终选中结构,因为它正在调用object.Equals(object o)
  4. 第四个有两个重载可用(object/T)所以我假设它也会避免装箱。但是,目标结构需要实现IEquatable<T>接口,使得辅助扩展方法不是很有帮助。
  5. 变体:

    public static bool IsDefault<T> (this T value)
        where T : struct
    {
        // Illegal since there is no way to know whether T implements the ==/!= operators.
        return (value == default(T));
    }
    
    public static bool IsDefault<T> (this T value)
        where T : struct
    {
        return (!EqualityComparer<T>.Default.Equals(value, default(T)));
    }
    
    public static bool IsDefault<T> (this T value)
        where T : struct
    {
        return (value.Equals(default(T)));
    }
    
    public static bool IsDefault<T> (this T value)
        where T : struct, IEquatable<T>
    {
        return (value.Equals(default(T)));
    }
    

    这个问题是关于确认上述假设,以及我是否误解和/或遗漏了什么。

2 个答案:

答案 0 :(得分:5)

  
      
  1. 以下第一种方法是非法的,因为结构不会隐式覆盖相等运算符== /!=。
  2.   

真。

  
      
  1. 第二个“出现”以避免拳击。
  2.   

被调用方法的签名是EqualityComparer<T>.Equals(T,T),它使用类型T作为参数,所以它不需要装箱来调用。

默认比较器的实现检查T是否为IEquatable<T>,如果是,则使用使用IEquatable<T>.Equals的比较器,否则使用Object.Equals的比较器,因此内部存在如果结构不是IEquatable('仅在需要时'),则可能应用装箱。

  
      
  1. 第三种方法应该总是选中struct,因为它调用了object.Equals(object o)。
  2.   

真。

  
      
  1. 第四个有两个可用的重载(对象/ T),所以我假设它也会避免装箱。但是,目标结构需要实现IEquatable接口,这使得辅助扩展方法不是很有帮助。
  2.   

是的,根据this SO answer,它不需要拳击。这是T : IEquatable

中针对EqualityComparer<T>.Default特定情况的有效代码

答案 1 :(得分:2)

让我补充一点,对于struct,如果不定义比较,则细节变得复杂。

例如How to define value equality for a type说:

您定义的任何结构都已经具有默认的实现值相等的方法,该实现继承自 Object.Equals(Object)方法的System.ValueType重写。此实现使用反射来检查类型中的所有字段和属性。尽管此实现产生正确的结果,但与专门为该类型编写的自定义实现相比,它相对较慢。

有关更多详细信息,另请参见Performance implications of default struct equality in C#

Equals和GetHashCode有一个优化的默认版本,但是您永远不要依赖它,因为您可能会因为无辜的代码更改而停止点击它。