Search code examples
c#reflectionsystem.reflection

Is it possible to use reflection to compare two arrays with the same element types?


My class looks something like this:

public class Test
{
    public A[] ArrayA { get;set; }
}

public class A
{
    public string P1 { get;set; }
    public int P2 { get;set; }
}

Suppose I have two objects of Test class. I want to use reflection to compare the two, assuming that the array length of both ArrayA properties are the same in both objects. For example:

Test a = new Test();
Test b = new Test();

// fill them with some info.

var props = typeof(Test).GetProperties();

foreach (var prop in props)
{
    var arrayA = prop.GetValue(a);
    var arrayB = prop.GetValue(b);

    for (int i = 0; i < arrayA.Lenght; i++)
    {
        var item1 = arrayA.GetValue(i);
        var item2 = arrayB.GetValue(i);
    
        // Do Comparison of item1 and item2
    }
}

So here's where I run into a problem. item1 and item2 are both of type object. I can't seem to get the original type from it. I can get the Type from the array, how do I use that to get the properties I want in item1 and item2? I want to use reflection to grab the property information of item1 and item2 in order to make the comparison. Is this doable?

FYI. I'm not interested in any other solutions outside of using reflection. I already how to do those.


Solution

  • While it is possible to do in reflection it will be slow, and you'll find yourself battling all kinds of edge cases when your object(s) start to get complicated. But for your simple example which has an array and an objects with simple string/int properties the following works how (I think) you expected.

    public static bool AreEqual(object a, object b)
    {
        var props = a.GetType().GetProperties();
        foreach (var prop in props)
        {
            if(prop.PropertyType.IsArray)
            {
                var arrayA = (Array)prop.GetValue(a);
                var arrayB = (Array)prop.GetValue(b);
                if(!AreArraysEqual(arrayA, arrayB))
                {
                    return false;
                }
            }
            else
            {
                if(!prop.GetValue(a).Equals(prop.GetValue(b)))
                {
                    return false;
                }
            }
        }
        return true;
    }
    
    public static bool AreArraysEqual(Array a, Array b)
    {
        for(var i=0;i<a.Length;i++)
        {
            if(!AreEqual(a.GetValue(i),b.GetValue(i)))
            {
                return false;
            }
        }
        return true;
    }
    

    This can then be tested as follows:

    Test a = new Test(){ ArrayA = new[]{ new A{P1 = "Foo", P2=1},new A{P1 = "Bar", P2=2}} };
    Test b = new Test(){ ArrayA = new[]{ new A{P1 = "Foo", P2=1},new A{P1 = "Bar", P2=2}} };
    Test c = new Test(){ ArrayA = new[]{ new A{P1 = "Foo", P2=2},new A{P1 = "Bar", P2=2}} };
    Console.WriteLine(AreEqual(a,b)); // true
    Console.WriteLine(AreEqual(a,c)); // false
    

    Live example: https://dotnetfiddle.net/FN8ZLu