0

I'm trying to set up a way to compare some nested lists with objects that I'm importing from MongoDB. I have already set up the lists object:

public class SecurityGroup
{
    public ObjectId Id { get; set; }
    public string GroupID { get; set; } 
    public string GroupName{ get; set; }
    public List<IpPermission> IpPermissions { get; set; }

    public override string ToString()
    {

        return string.Format("groupid : {0}, groupname : {1} ", GroupID, GroupName ); 
    }

With in that class I also have an overridden Equals method in place.

public override bool Equals(object obj)
    {
        SecurityGroup secGroup = obj as SecurityGroup;
        if (secGroup == null)
        {
             return false;
        }
        if (!string.Equals(GroupID, secGroup.GroupID, StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }
        if (!string.Equals(GroupName,secGroup.GroupName, StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

I'm not sure if I need to post the class used for the nested loop but there's an IEquatable interface and the entireity of this class is EXACTLY like the SecurityGroup class I just posted.

//Compare IpPermissions
        var diff1 = IpPermissions.Except(secGroup.IpPermissions);
        var diff2 = secGroup.IpPermissions.Except(IpPermissions);

        if (diff1.Any() || diff2.Any())
        {
            return false;
        }

        return true;
    }

Now here's the Hashcode method that I set up:

    public override int GetHashCode()
    {
        unchecked
        {
            const int HashingBase = (int)2166136261;
            const int HashingMultiplier = 16777619;
            int hash = HashingBase;
            hash = (hash * HashingMultiplier) ^ (!Object.ReferenceEquals(null, IpPort) ? IpPort.GetHashCode() : 0);
            hash = (hash * HashingMultiplier) ^ (!Object.ReferenceEquals(null, IpProtocol) ? IpProtocol.GetHashCode() : 0);
            hash = (hash * HashingMultiplier) ^ (!Object.ReferenceEquals(null, IpRanges) ? IpRanges.GetHashCode() : 0);
            return hash;
        }
    }

}

} That essentially conludes the code I have in place to set up the framework for my comparesList method. Now here's where I'm having issues. I'm trying to set up the compare lists method and it's just giving me underscored red lines on the 'public static' part. The thing I can't figure out is the error it's giving me for the 'foreach' statements. It's saying, "Cannot convert element type 'AwsInstanceProfile1.Entity.SecurityGroup' to iterator type 'Amazon.EC2.Model.SecurityGroup'" Which is really weird because I should in theory have the framework set up to allow the lists into these objects. Here's the rest of the method:

            public static bool CompareLists(List<Entity.SecurityGroup> list1, List<Entity.SecurityGroup> list2) =>
        {
            if (list1 == null || list2 == null)
                return list1 == list2;

            Dictionary<SecurityGroup, int> hash = new Dictionary<SecurityGroup, int>();

            foreach (SecurityGroup secGroup in list1)
            {
                if (hash.ContainsKey(secGroup))
                {
                    hash[secGroup]++;
                }

                else
                {
                    hash.Add(secGroup, 1);
                }
            }

            foreach (SecurityGroup secGroup in list2)
            {
                if (!hash.ContainsKey(secGroup) || hash[secGroup] == 0)
                {
                    return false;
                }
                hash[secGroup]--;
            }

            return true;

        }
  • I wouldn't implement "deep-comparison" in an `Equals` method if the type is not immutable. `Equals` is used too often implicitly. It should also go hand in hand with `GetHashCode`, which should always return the same value. So it should not depend on changeable data. I would put this into a `AreAllValuesEqual` method or `HasSameContents` or something or use a separate comparer to be used in lists (not for dictionary keys however and probably not in a `HashSet`, unless you don't change the data while it is there). – Stefan Steinegger Jun 21 '16 at 17:52
  • Well the types are immutable. They should be static and unchanging and more or less I'm just comparing the same lists over time to find the small difference of what's changed. – Carlton Peterson Jun 21 '16 at 18:07
  • Ok, then you are fine. You should still consider the performance impact of always having this way of comparison by default. Equals is called implicitly. Writing a comparer would give you more control when this way of comparison is used. – Stefan Steinegger Jun 21 '16 at 18:13
  • Performance was a huge worry for me but my supervisor showed me with the small size of the lists (maybe a few thousand) it won't take more than a second to complete. However, would you mind explaining to me what a comparer is, how it differentiates from this and the implications of trying to implement this on my existing code? – Carlton Peterson Jun 21 '16 at 18:17
  • See https://msdn.microsoft.com/en-us/library/ms132123%28v=vs.110%29.aspx To probably all classes and methods in the framework which use `Equals` and `GetHashCode` you can pass in your own equality comparer. (E.g. the `Distinct()` method, or the `Dictionary` class). The equality comparer implements `Equals` and `GetHashCode` outside of the class which is to be compared. – Stefan Steinegger Jun 21 '16 at 18:23

0 Answers0