Overloading == operator for class containing only string attributes

♀尐吖头ヾ 提交于 2019-12-11 11:57:32

问题


What would be the best (most elegant or performing) way of overloading the equality operator on a class containing only string attributes?

Example:

class MagicClass
{
    public string FirstAttribute { get; set; }
    public string SecondAttribute { get; set; }
    public string ThirdAttribute { get; set; }
    public string FourthAttribute { get; set; }
    public string FifthAttribute { get; set; }
}

I know how to overload the operator itself, however, I am wondering about the following points:

  1. Is there a way to elegantly compare such two objects (e.g. without having to write an if statement containing mutual comparisons of all the attributes
  2. What would be a good implementation of the GetHashCode() method in such case

回答1:


How about something like this, Just create array of all properties and a loop.

internal class MagicClass
{
    public string FirstAttribute { get; set; }
    public string SecondAttribute { get; set; }
    public string ThirdAttribute { get; set; }
    public string FourthAttribute { get; set; }
    public string FifthAttribute { get; set; }

    private string[] AllProperties//Array of all properties
    {
        get
        {
            return new[]
            {
                FirstAttribute,
                SecondAttribute,
                ThirdAttribute,
                FourthAttribute,
                FifthAttribute
            };
        }
    }

    protected bool Equals(MagicClass other)
    {
        var thisProps = this.AllProperties;
        var otherProps = other.AllProperties;

        return thisProps.SequenceEqual(otherProps);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((MagicClass) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var thisProps = this.AllProperties;
            int hashCode = 0;
            foreach (var prop in thisProps)
            {
                hashCode = (hashCode * 397) ^ (prop != null ? prop.GetHashCode() : 0);
            }
            return hashCode;
        }
    }
}

Then you can call Equals method inside your operator overload. If you're lazy to create AllProperties array you can use Reflection but IMO reflection is overkill here.




回答2:


Not saying this is the 'best' or the most elegant solution, but I'd have the tendency to use an array and an index initializer, using an enumeration, so I could reuse get and set logic and in this case reset a hash code for a quick first comparison. The advantage of the enumeration is, that you don't have to recheck your compare logic when an attribute is added, and you can prevent the overhead of resorting to reflection.

class MagicClass
{
    string[] Values = new string[Enum.GetValues(typeof(MagicClassValues)).Length];

    public string this[MagicClassValues Value] //and/or a GetValue/SetValue construction
    {
        get
        {
            return Values[(int)Value];
        }
        set
        {
            Values[(int)Value] = value;
            hash = null;
        }
    }

    int? hash; //buffered for optimal dictionary performance and == comparisson
    public override int GetHashCode()
    {
        if (hash == null)
            unchecked
            {
                hash = Values.Sum(s => s.GetHashCode());
            }
        return hash.Value;
    }

    public static bool operator ==(MagicClass v1, MagicClass v2) //used == operator, in compliance to the question, but this would be better for 'Equals'
    {
        if(ReferenceEquals(v1,v2))return true;
        if(ReferenceEquals(v1,null) || ReferenceEquals(v2,null) || v1.GetHashCode() != v2.GetHashCode())return false;
        return v1.Values.SequenceEqual(v2.Values);
    }
    public static bool operator !=(MagicClass v1, MagicClass v2)
    {
        return !(v1 == v2);
    }

    //optional, use hard named properties as well
    public string FirstAttribute { get { return this[MagicClassValues.FirstAttribute]; } set { this[MagicClassValues.FirstAttribute] = value; } }
}

public enum MagicClassValues
{
    FirstAttribute,
    SecondAttribute,
    //etc
}


来源:https://stackoverflow.com/questions/23340372/overloading-operator-for-class-containing-only-string-attributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!