如何将两个通用对象与嵌套集合进行比较

时间:2022-10-09 14:29:17

I have been working on a generic method to compare two of the same objects to test wether the values in each one are equal.

我一直在研究一种通用的方法来比较两个相同的对象,以测试每个对象中的值是否相等。

I am stuck on trying to compare System.Collection.Generic objects, such as Dictionary, HashSet, LinkedList, Stack, ect...

我坚持尝试比较System.Collection.Generic对象,如Dictionary,HashSet,LinkedList,Stack等...

The one i can compare on is the List collection.

我可以比较的是List集合。

Below is what I have so far. if you can provide a means to compare the generics I'd be greatly appreciative.

以下是我到目前为止的情况。如果你能提供一种比较仿制药的方法,我将非常感激。

~Starts the recursive compare

〜开始递归比较

public static bool FullCompare<T>(this T source, T compareTo, bool ignoreCase)
{
    return recursiveCompare(source, compareTo, ignoreCase, true);
}

~The recursive search

〜递归搜索

private static bool recursiveCompare<T>(T source, T compareTo, bool ignoreCase, bool isEqual)
{
    if (source == null || compareTo == null) return isEqual;
    if(!isEqual) return isEqual;

    Type sourceType = source.GetType();
    Type compareToType = compareTo.GetType();

    if (sourceType.IsPrimitive || source is string) return Test(source, compareTo, ignoreCase);  

    var sourceProperties = sourceType.GetProperties();
    var compareToProperties = compareToType.GetProperties();

    for (var property = 0; property < sourceProperties.Count(); property++ )
    {
        var sourceProperty = sourceProperties[property];
        var compareToProperty = compareToProperties[property];

        object sourceValue = sourceProperty.GetValue(source, null);
        object compareToValue = compareToProperty.GetValue(compareTo, null);

        var sourceElements = sourceValue as IList;
        var compareToElements = compareToValue as IList;

        if (sourceElements != null)
        {
            for (var element = 0; element < sourceElements.Count; element++)
            {
                isEqual = recursiveCompare(sourceElements[element], compareToElements[element], ignoreCase, isEqual);
            }
        }
        else if (typeof(IEnumerable).IsAssignableFrom(sourceProperty.PropertyType))
        {
            //compare System.Collection.Generic objects
        }
        else
        {
            if (sourceProperty.PropertyType.Assembly == sourceType.Assembly)
            {
                isEqual = recursiveCompare(sourceValue, compareToValue, ignoreCase, isEqual);
            }
            else
            {
                isEqual = Test(sourceValue, compareToValue, ignoreCase);
            }
        }
    }
    return isEqual;
}

~ The comparison test

〜比较测试

private static bool Test<T>(T a, T b, bool ignoreCase)
{
    if (a == null && b == null)
    {
        return true;
    }
    else if (a == null)
    {
        return false;
    }
    else if (b == null)
    {
        return false;
    }
    else if (a is string)
    {
        if (ignoreCase)
        {
            var aAsString = Convert.ToString(a);
            var bAsString = Convert.ToString(b);
            return aAsString.EqualsIgnoreCaseAndWhitespace(bAsString);
        }
    }
    return EqualityComparer<T>.Default.Equals(a, b);
}

These are the test cases I am using to test the function

这些是我用来测试函数的测试用例

    public class A
    {
        public string TestA { get; set; }
        public List<String> ListA { get; set; }
    }

    public class test
    {
        public byte? byte1 { get; set; }
        //public Dictionary<int, byte> byteDictionary { get; set; }
        public HashSet<byte> byteHashSet { get; set; }
        public LinkedList<byte> byteLinkedList { get; set; }
        public List<byte> byteList { get; set; }
        public Queue<byte> byteQueue { get; set; }
        public Stack<byte> byteStack { get; set; }
        public sbyte? sbyte1 { get; set; }
        public short? short1 { get; set; }
        public ushort? ushort1 { get; set; }
        public int? int1 { get; set; }
        public uint? uint1 { get; set; }
        public long? long1 { get; set; }
        public ulong? ulong1 { get; set; }
        public float? float1 { get; set; }
        public double? double1 { get; set; }
        public char? char1 { get; set; }
        public string string1 { get; set; }
        public decimal? decimal1 { get; set; }
        public bool? bool1 { get; set; }
        public DateTime datetime1 { get; set; }
        public TimeSpan timespan1 { get; set; }
        public string string1Var;
        public A objectA { get; set; }
    }

        var byteAList = new List<byte>();
        byteAList.Add(1);
        byteAList.Add(2);

        var byteBList = new List<byte>();
        byteBList.Add(1);
        byteBList.Add(2);

        //var byteADictionary = new Dictionary<int,byte>();
        //byteADictionary.Add(1,1);

        //var byteBDictionary = new Dictionary<int,byte>();
        //byteBDictionary.Add(1,1);

        var dateTimeA = new DateTime(1,1,1,1,1,1);            
        var dateTimeB = new DateTime(1,1,1,1,1,1);

        var timeSpanA = new TimeSpan(1,1,1,1,1);            
        var timeSpanB = new TimeSpan(1,1,1,1,1);

        var aAListAList = new List<string>();
        aAListAList.Add("Nel");
        aAListAList.Add("Hello");

        var aA = new A()
        {
            TestA = "Jar"
            , ListA = aAListAList
        };

        var aAListBList = new List<string>();
        aAListBList.Add("Nel");
        aAListBList.Add("Hello");
        var aB = new A()
        {
            TestA = "Jar"
            ,
            ListA = aAListBList
        };

        var byteHashSetA = new HashSet<byte>();
        byteHashSetA.Add(1);
        byteHashSetA.Add(2);

        var byteHashSetB = new HashSet<byte>();
        byteHashSetB.Add(1);
        byteHashSetB.Add(2);

        var a = new test() 
        { 
            byte1 = 1
            , byteList = byteAList
            //, byteDictionary = byteADictionary
            , byteHashSet = byteHashSetA
            , sbyte1 = -1
            , short1 = -11
            , ushort1 = 11
            , int1 = -1
            , uint1 = 1
            , long1 = 1
            , ulong1 = 1
            , float1 = 1.1F
            , double1  = 1.1
            //, char1 = 't'
            , string1 = "test"
            , decimal1 = 1.1M
            , bool1 = true
            , datetime1 = dateTimeA
            , timespan1 = timeSpanA 
            , string1Var = null
            , objectA = aA
        };
        var a2 = new test()
        {
            byte1 = 1
            ,
            byteList = byteBList
            //,
            //byteDictionary = byteBDictionary
            ,
            byteHashSet = byteHashSetB
            ,
            sbyte1 = -1
            ,
            short1 = -11
            ,
            ushort1 = 11
            ,
            int1 = -1
            ,
            uint1 = 1
            ,
            long1 = 1
            ,
            ulong1 = 1
            ,
            float1 = 1.1F
            ,
            double1 = 1.1
            ,
            char1 = 't'
            ,
            string1 = "test"
            ,
            decimal1 = 1.1M
            ,
            bool1 = true
            ,
            datetime1 = dateTimeB
            ,
            timespan1 = timeSpanB
            ,
            string1Var = null
            ,
            objectA = aB
        };

        var equal = a.FullCompare(a2, true);

1 个解决方案

#1


0  

I solved the issue by comparing the lengths of the two objects first. then if they are the same then i do a nested loop to compare one list against the other. now this is probably not efficient, but it works.

我首先通过比较两个对象的长度来解决问题。然后,如果它们是相同的,那么我做一个嵌套循环来比较一个列表与另一个列表。现在这可能效率不高,但它确实有效。

foreach (var sourceElement in sourceElements) { numOfSourceElements++; }

foreach (var compareToElement in compareToElements) { numOfCompareToElements++; }

if (numOfSourceElements != numOfCompareToElements) isEqual = false;

if (isEqual) 
{ 
    foreach (var sourceElement in sourceElements)
    {
        found = false;
        foreach (var compareToElement in compareToElements) 
        {
            if (IsSameAsRecursive(sourceElement, compareToElement, sameAsOptions, isEqual))
            {
                found = true;
                break;
            }
        }
        if (!found) break;
    }
    isEqual = found;
}

#1


0  

I solved the issue by comparing the lengths of the two objects first. then if they are the same then i do a nested loop to compare one list against the other. now this is probably not efficient, but it works.

我首先通过比较两个对象的长度来解决问题。然后,如果它们是相同的,那么我做一个嵌套循环来比较一个列表与另一个列表。现在这可能效率不高,但它确实有效。

foreach (var sourceElement in sourceElements) { numOfSourceElements++; }

foreach (var compareToElement in compareToElements) { numOfCompareToElements++; }

if (numOfSourceElements != numOfCompareToElements) isEqual = false;

if (isEqual) 
{ 
    foreach (var sourceElement in sourceElements)
    {
        found = false;
        foreach (var compareToElement in compareToElements) 
        {
            if (IsSameAsRecursive(sourceElement, compareToElement, sameAsOptions, isEqual))
            {
                found = true;
                break;
            }
        }
        if (!found) break;
    }
    isEqual = found;
}