2016-04-24 39 views
6

我遇到了一个扩展方法,该方法适用于结构(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>接口,使辅助扩展方法不是很有帮助。

变化:

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

这个问题是关于确认上述假设,如果我误解和/或留下一些东西。

回答

4
  1. 第一下列方法是非法的,因为结构不隐含重写等式运算符== /!=。

是的。

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

的调用方法的签名是EqualityComparer<T>.Equals(T,T)它使用类型T的参数,所以它不需要拳击打电话。

('只在需要

默认的比较检查的实施,如果 TIEquatable<T>,如果是使用使用 IEquatable<T>.Equals和其他一个比较器用来 Object.Equals一个比较器,所以在内部有可能是拳击应用,如果结构不 IEquatable “)。

  • 第三种方法应该总是框中的结构,因为它调用的Object.Equals(对象o)。
  • 是的。

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

    是,它不需要拳击,按this SO answer。这是您从EqualityComparer<T>.Default针对T : IEquatable的特定情况获得的有效代码。

    +0

    谢谢。所以我明白,第二种情况将需要拳击,如果它不实施IEquatable ?如果是这样,那么没有消费者(结构的创建者)实现一个接口(进行更多的工作只是为了消费我们的库)而进行拆箱操作的方法都不是。 –

    +1

    拳击费用非常低,尤其是与典型的对象比较,所以我不会担心它的实际情况。如果一个结构体的创建者没有实现相等性,那么它就按照Object.Equals给出的默认相等性,所以然后boxing是不可避免的,但是与(字节比较/反射)Object.Equals的成本。 – MicroVirus

    +0

    Perf和成本是非常主观的。我遇到过这样的情景:即使是“自动公开财产”的成本,拳击成本也远远超过了这些情况。就我而言,我不得不为'Vector2'结构实现'public readonly'字段,这带来了对背景字段属性的一个荒谬的性能改进。但是这些都是专门的场景,开发人员已经足够了解提供相关的内置比较。除此之外,你可以评论一下:“第二个案例将需要拳击,如果它不实施IEquatable ?”。 –