代码之家  ›  专栏  ›  技术社区  ›  Jack Kada

写一个好的c等于方法

c#
  •  18
  • Jack Kada  · 技术社区  · 15 年前

    有人有一个模板来写一个像样的等值方法吗?我记得在有效的Java中,处理子类时,在处理等量时存在问题。

    我没有这本书,我不记得它是否是实用的建议——那么,如何编写一个可靠的、健壮的equals方法实现呢?

    8 回复  |  直到 9 年前
        1
  •  12
  •   Jon Skeet    15 年前

    可能是一个现成的建议,但:考虑不压倒一切 Equals 首先。正如您所提到的,基本上,平等的本质在子类化中并不适用。然而,在.NET API中,几乎所有使用相等(例如字典、哈希集)的地方都允许 IEqualityComparer<T> 被传进来。使一个不同的对象负责平等使生活更加灵活:您可以使用不同的对象来确定要使用的标准。

    实施 i质量公司<t> 更简单-您仍然需要检查无效性,但是您不需要担心类型是否合适,或者是否 等于 将被进一步覆盖。

    另一种使正常 等于 更顺利的工作是在大多数情况下完全避免继承——我不记得上次在我的代码中真正意义上的重写 等于 允许派生类。 sealed FTW:

        2
  •  8
  •   Justin Niessner    15 年前

    您可能已经这样做了,但是您是否查看了有关实现 Equals() ?

    Implementing the Equals Method

        3
  •  5
  •   Daniel Earwicker    15 年前

    如果你厌倦了为此编写大量样板文件,你可以尝试使用一个为你实现它的基类。

    public abstract class ValueObject<T> : IEquatable<T>
        where T : ValueObject<T>
    {
        protected abstract IEnumerable<object> Reflect();
    
        public override bool Equals(Object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (obj.GetType() != GetType()) return false;
            return Equals(obj as T);
        }
    
        public bool Equals(T other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Reflect().SequenceEqual(other.Reflect());
        }
    
        public override int GetHashCode()
        {
            return Reflect().Aggregate(36, (hashCode, value) => value == null ?
                                    hashCode : hashCode ^ value.GetHashCode());
        }
    
        public override string ToString()
        {
            return "{ " + Reflect().Aggregate((l, r) => l + ", " + r) + " }";
        }
    }
    

    现在要使类成为一个值,只需说:

    public class Person : ValueObject<Person>
    {
        public int Age { get; set; }
        public string Name { get; set; }
    
        protected override IEnumerable<object> Reflect()
        {
            return new object[] { Age, Name };
        }
    }
    

    Reflect 重写返回需要有助于相等的值序列。

    不幸的是,这种方法不能帮助声明 operator == 因为它必须在派生类型上特别声明。

        4
  •  5
  •   sjohnston    12 年前

    一个好的等价方法的性质:

    • 对称性 :对于两个引用,a和b,a.equals(b)if and only if b.equals(a)
    • 反身性 :全部 非空 参考文献,a.等于(a)
    • 传递性 :如果a.等于(b)和b.等于(c),则a.等于(c)
        5
  •  2
  •   uthark    15 年前
        6
  •  1
  •   ChaosPandion    15 年前

    我通常这样做:

    public struct EmailAddress : IEquatable<EmailAddress>
    {
        public override bool Equals(object obj)
        {
            return obj != null && obj.GetType() == typeof(EmailAddress) && Equals((EmailAddress)obj);
        }
    
        public bool Equals(EmailAddress other)
        {
            return this.LocalPart == other.LocalPart && this.Domain == other.Domain;
        }
    }
    
        7
  •  0
  •   AxelEckenberger    15 年前

    “good”等于方法是一种比较类中唯一部分的方法,同时忽略不影响唯一性的部分。因此,如果您有一个具有唯一ID的类,那么您可以使用它来建立相等性,而不考虑任何其他属性。不过,通常您也需要一些时间戳值。

        8
  •  0
  •   Asia    9 年前

    社会阶层人士 { 公共字符串名称get;set;

        public int Age { get; set; }
    
        public override bool Equals(object obj)
        {
            var objAsPerson = obj as Person;
    
            if (obj == null)
            {
                return false;
            }
    
            if (this.Name != objAsPerson.Name)
            {
                return false;
            }
    
            if (this.Age != objAsPerson.Age)
            {
                return false;
            }
    
            return true;
        }
    }