1

I'm implementing generic objects comparing method to compare instances of classes in my project. In each class I have some value type variable and some bindinglist of its associate class. With value type variable, I can use == operator or equal operator to compare it, but with bindinglist, I don't know how to cast it to bindinglist<type of associate class> to iterate through it and perform recursion.

public bool IsEqual<T>(T obj1, T obj2)
{
    PropertyInfo[] prop1 = obj1.GetType().GetProperties();
    PropertyInfo[] prop2 = obj2.GetType().GetProperties(); 

    for(int i = 0; i < prop1.Count; i++)
    {
        if(prop1[i].IsValueType && prop2[i].IsValueType)
        {
            if(prop1.GetValue(i) != prop2.GetValue(i))
                return false
        }
        else
        {
            //This is bindinglist of associate class
            //I need to cast it to iterate in perform recursion here            
        }
    }

    return true
}

So how can I implement recursion when property is a bindinglist?

P/S: forgive my bad English

UPDATE:

After consider carefully, I implemented IEqualtable as Mr. Stephen Hewlett suggested. Thank you very much, Mr. Stephen Hewlett. And for those who still want to use compare function, I'll give you an approach that I think it will work:

public bool IsEqual(Object obj1, Object obj2)
{
    PropertyInfo[] prop1 = obj1.GetType().GetProperties();
    PropertyInfo[] prop2 = obj2.GetType().GetProperties(); 

    for(int i = 0; i < prop1.Count; i++)
    {
        if(prop1[i].IsValueType && prop2[i].IsValueType)
        {
            if(prop1[i].GetValue(obj1, null) != prop2[i].GetValue(obj2, null))
                return false;
        }
        else if (prop1[i].PropertyType.IsGenericType && prop2[i].PropertyType.IsGenericType) //if property is a generic list
        {
            //Get actual type of property
            Type type = prop1[i].PropertyType;

            //Cast property into type
            var list1 = Convert.ChangeType(prop1[i].GetValue(obj1, null), type);
            var list2 = Convert.ChangeType(prop1[i].GetValue(obj2, null), type);

            if (list1.count != list2.count)
                return false;

            for j as integer = 0 to list1.Count - 1
            {
                //Recursion here
                if (!IsEqual(list1(j), list2(j)))
                {
                    return false;
                }
            }
        }
        else //if property is instance of a class
        {
            Type type = prop1[i].PropertyType;
            Object object1 = Convert.ChangeType(prop1[i].GetValue(obj1, null), type);
            Object object2 = Convert.ChangeType(prop1[i].GetValue(obj2, null), type);

            //Recursion
            if(!IsEqual(object1, object2))
            {
                 return false;
            }
        }
    }

    return true;
}
13
  • What do you actually want the code to do? Commented Aug 26, 2013 at 3:13
  • At the else phrase, prop1[i] and prop2[i] is a bindinglist of associate class. EX: obj1 and obj2 is instance of Foo, and both obj1 and obj2 include a binding list of Bar. So at the else phrase I need to cast prop1[i] and prop2[i] to BindingList<Bar> or any type that I can iterate through it and perform recursion Commented Aug 26, 2013 at 3:16
  • I'm not sure you need to use reflection at all to do this... what is the overall aim of the method? What types will be passed into it? Commented Aug 26, 2013 at 3:18
  • 1
    Firstly, this code is not Generic, therefore there is no need to cast to IEnumerable<TChild> to then invoke IsEqual() on each child. Each of the methods you use in IsEqual could equally work on System.Object. Secondly, usage of generics in reflection is not very nice. Thirdly, given the signature of the method, it looks like you intend to use it everywhere as library code, hence I would HIGHLY advise against reflection, as it is extremely slow compared to inlined code. Commented Aug 26, 2013 at 3:42
  • 1
    I would advise you to use IEqualityComparer instead if you prefer not to modify your classes. If need be, use code generation/IL generation/Expression trees/anything except reflection for implementing the IEqualityComparers. Commented Aug 26, 2013 at 3:43

1 Answer 1

4

I would very very strongly recommend implementing IEquatable for all your classes - nomatter how many of them there are - as using reflection for something that does not need it is usually a bad idea. A fundamental advantage of C# is the type safety you get by using all the built in type features. By using reflection you are trying to imitate what C# and .NET does for you already, and you will probably get it wrong.

Your method does not need to be generic as it is using reflection, so the objects in question will be passed to the reflection methods as object anyway. There is no advantage to adding the type parameter. Without the type parameter it will be easier for you to cast the binding list as you need to.

Sign up to request clarification or add additional context in comments.

2 Comments

I got it, thank for your time and your suggestion. Have a nice day, Mr. Stephen Hewlett :)
A valid alternative to IEquatable is to use IEqualityComparer as an external class. However, I agree that I would strongly recommend you implementing IEquatable if possible. If you want to reduce the amount of code you write, you could generate the IEquatable code at compile time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.