【问题标题】:c# struct with no reference typesc# 没有引用类型的结构
【发布时间】:2018-07-01 02:28:39
【问题描述】:

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

考虑到这个结构将在集合中使用,我希望它表现得像一个值类型(即 int)。

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

【问题讨论】:

    标签: c# c#-7.0


    【解决方案1】:
    1. 取决于您,默认情况下 == 和 != 将重定向到默认的 Equals 实现,但直接使用 Equals 而不是 == 或 != 被认为是更好的做法
    2. 默认情况下,您应该 Equals 对值类型执行按位比较,对引用类型执行引用相等,因此,如果您的结构包含引用类型的字段,则需要覆盖 Equals 以对它们执行适当的比较。除此之外,MSDN 还是建议覆盖 Equals,以提高性能。

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

    1. 结构体在变量/方法之间传递时默认被复制,因此无需编写复制构造函数。我能想到的唯一情况是,如果您的结构包含引用类型的字段,并且您想要创建一个复制构造函数来对它们执行深度复制,这取决于您。
    2. 担心分配是什么意思?
    3. 是的。如果要将结构用作 HashSet 的成员或字典中的键,则需要提供 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 进行比较,您也应该这样做。

    所以不,不需要实现 == 和 !=。

    【讨论】:

    • 我的问题特别是询问不包含引用类型的情况。请相应地编辑您的答案
    • @kofifus 抱歉,一开始没听懂。如果没有引用类型,我的回答仍然成立,我只是详细说明了结构中确实有引用类型的情况。我仍然建议提供你自己的 Equals 实现,如果你每次都改变一些东西——添加引用类型,想忽略某个字段,这将证明是有用的。
    • 所以在这种情况下我可以不用 ==、!= 和 Equals 吗?
    • @kofifus 是的,Equals 就足够了,作用于数组/字典的成员/键的方法调用 .Equals 进行比较,它们不使用 == 和 != 运算符。我忘了提及它,但最好实现 IEquatable 因为这样您就可以避免在调用默认 Equals(object) 时发生的拆箱(将结构分配到内存)
    • 我不明白,如果我不覆盖 ==、!= 和 Equals 会怎样?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 2012-07-23
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    相关资源
    最近更新 更多