繁体   English   中英

在没有装箱的情况下比较结构的相等性

[英]Comparing structs for equality without 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>接口,这使得辅助扩展方法不是很有用。

变化:

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

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

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

没错。

  1. 第二个“出现”是为了避免拳击。

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

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

  1. 第三种方法应该总是装箱结构,因为它正在调用 object.Equals(object o)。

没错。

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

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

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

例如如何为类型定义值相等说:

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

有关更多详细信息,另请参阅C# 中默认结构相等的性能影响,包括:

Equals 和 GetHashCode 有一个优化的默认版本,但你永远不应该依赖它,因为你可能会因为一个无辜的代码更改而停止使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM