Generic equality checker I use this method to check if two reference types are equal

  public static bool AreEquals&lt;T&gt;(T source, object obj) where T : class
  {
     if (ReferenceEquals(source, obj))
        return true;

     var convertedTarget = obj as T;

     if (ReferenceEquals(convertedTarget, null))
        return false;

     List&lt;object&gt; equalityMembers = typeof (T).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(p =&gt; p.GetCustomAttribute&lt;EqualityMemberAttribute&gt;() != null).ToList&lt;object&gt;();
     equalityMembers.AddRange(typeof(T).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(p =&gt; p.GetCustomAttribute&lt;EqualityMemberAttribute&gt;() != null).ToList&lt;object&gt;());

     if (equalityMembers.Count == 0)
        return false; //The references were not equals and there is nothing to compare..

     var enumerator = equalityMembers.GetEnumerator();
     bool areEquals = true;

     while (enumerator.MoveNext() &amp;&amp; areEquals)
     {
        var current = enumerator.Current;

        //On sait que FieldInfo et PropertyInfo ont la méthode GetValue
        var methodInfo = current.GetType().GetMethod("GetValue", new [] {typeof (object)});

        object valueSource = methodInfo.Invoke(current, new object[] {source});
        object valueObj = methodInfo.Invoke(current, new object[] {convertedTarget});

        areEquals = valueSource.Equals(valueObj);
     }
     return areEquals;
  }


I use attributes on properties/fields to find which of them are used to decide if the two objects are equals ex :

public class MyClass
{
    [EqualityMember]
    public int ID{get;set;}

    public override Equals(object obj)
    {
        return MyStaticClass.AreEquals(this,obj);
    }
}


It works very well but I am bothered with how I get the properties and fields in a list and use reflection to invoke the GetValue method, would you have any other alternatives? Or is there anything that seems flawed in my method?
I took a shot at this as well. I think @Hangy had a few good ideas but ended up with a rather complex solution. I haven't added any caching so you might want to add that yourself afterwards.

What I changed: 


Different check for null which is clearer in my opinion.
Braces for one-line statements.
Extracted member parsing to a separate method.
Instead of holding all data of PropertyInfo and FieldInfo, I simply use a Dictionary&lt;string, object&gt; which translates to &lt;FieldName, FieldValue&gt;.
Unused properties and fields data is eligible for GC as soon as you extracted the needed information.
Got rid of the Enumerator and added some juicy LINQ.


The end result:

public static class EqualityAttribute
{
    public static bool AreEquals&lt;T&gt;(T source, object obj) where T : class
    {
        if (ReferenceEquals(source, obj))
        {
            return true;
        }

        var convertedTarget = obj as T;
        if (convertedTarget == null)
        {
            return false;
        }

        var obj1Members = GetFieldEqualityMembers(source);
        var obj2Members = GetFieldEqualityMembers(obj);

        var noMembersToCompare = obj1Members.Values.Count == 0 &amp;&amp; obj2Members.Values.Count == 0;
        if (noMembersToCompare)
        {
            return false;
        }

        if (obj1Members.Keys.Any(key =&gt; !obj1Members[key].Equals(obj2Members[key])))
        {
            return false;
        }

        return true;
    }

    private static Dictionary&lt;string, object&gt; GetFieldEqualityMembers&lt;T&gt;(T obj)
    {
        var properties = obj.GetType().GetProperties(BindingFlags.Public |
                                                     BindingFlags.NonPublic |
                                                     BindingFlags.Instance)
            .Where(x =&gt; x.GetCustomAttribute&lt;EqualityMemberAttribute&gt;() != null)
            .ToDictionary(x =&gt; x.Name, x =&gt; x.GetValue(obj));

        var fields = obj.GetType().GetFields(BindingFlags.Public |
                                             BindingFlags.NonPublic |
                                             BindingFlags.Instance)
            .Where(x =&gt; x.GetCustomAttribute&lt;EqualityMemberAttribute&gt;() != null)
            .ToDictionary(x =&gt; x.Name, x =&gt; x.GetValue(obj));

        properties.ToList().ForEach(x =&gt; fields.Add(x.Key, x.Value));
        return fields;
    }
}