没有引用类型的c#结构

时间:2018-07-01 02:28:39

标签: c# c#-7.0

考虑一个不包含任何引用字段的结构(仅基本类型和其他结构)。

考虑此结构将用于集合中,我希望它的行为类似于值类型(即int)。

  • 我是否需要重写operator ==和operator!=?
  • 我需要覆盖等于吗?
  • 我需要复制构造函数吗?
  • 我需要担心分配吗?
  • 我需要重写GetHashCode吗?

1 个答案:

答案 0 :(得分:3)

  1. 取决于您,默认情况下==和!=将重定向到默认的Equals实现,但是,最好直接使用Equals代替==或!=
  2. 默认情况下,您应该使用Equals对值类型进行按位比较,并对引用类型进行引用相等,因此,如果您的结构包含作为引用类型的字段,则需要覆盖Equals才能对其进行正确的比较。除此之外,MSDN建议无论如何都要覆盖Equals,以提高性能。
  

尤其是如果您的值类型包含引用的字段   类型,则应重写Equals(Object)方法。这样可以改善   性能,使您能够更紧密地代表   类型相等。

  1. 在变量/方法之间传递结构时,默认情况下会复制结构,因此无需编写复制构造函数。我能想到的唯一情况是,如果您的结构包含作为引用类型的字段,并且您想创建一个复制构造函数,对它们执行深度复制,具体取决于您。
  2. 您对分配有什么担心?
  3. 是的。如果要将结构用作HashSet的成员或Dictionary中的键,则需要提供GetHashCode的自定义实现。

最好实现IEquatable以避免装箱(默认Equals接受对象类型,因此您的结构将必须进行装箱以适合该类型)。 集合(数组,字典等)通常会检查其成员是否实现IEquatable,并将使用IEquatable.Equals,因此最好实现它。 还建议实现默认的Equals(来自System.Object)并直接指向IEquatable.Equals实现。 示例:

struct MyStruct : IEquatable<MyStruct>
{
    public int A { get; set; }

    public int B { get; set; }

    public bool Equals(MyStruct other)
    {
        return A == other.A && B == other.B;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is MyStruct)) return false;
        return ((MyStruct)obj).Equals(this);
    }

    public override int GetHashCode()
    {
        return (A, B).GetHashCode();
    }
}

我还提供了一个如何实现GetHashCode的示例,最好的方法是使用Tuple的实现。

再次执行==和!=由您决定 标准库(System,System.Collections等)使用System.Equals或IEquatable.Equals进行比较,您也应该这样做。

因此,不需要==和!=。