6

I've two dictionaries like:

Dictionary<string, object> dict1 = new Dictionary<string, object>();
Dictionary<string, object> dict2 = new Dictionary<string, object>();

I want to compare them where few entries are List<Enum>, how can I compare these List<Enum> objects. Please see following sample code:

enum Days { Monday, Tuesday, Wednesday }
enum Colors { Red, Green, Blue }
enum Cars { Acura, BMW, Ford }

Populating dictionaries:

List<Days> lst1 = new List<Days>();
List<Days> lst2 = new List<Days>();

lst1.Add(Days.Monday); lst1.Add(Days.Tuesday); 
lst2.Add(Days.Monday); lst2.Add(Days.Tuesday);

dict1.Add("DayEnum", lst1);
dict2.Add("DayEnum", lst2);

foreach (KeyValuePair<string, object> entry in dict1)
{
    var t1 = dict1[entry.Key];
    var t2 = dict2[entry.Key];

    if (dict1[entry.Key].GetType().IsGenericType && Compare(dict1[entry.Key], dict2[entry.Key]))
    {
                // List elements matches...
    } 
    else if (dict1[entry.Key].Equals(dict2[entry.Key]))
    {
                // Other elements matches...
    }
}

It doesn't match unless I provide the exact Enum i.e. IEnumerable<Days> but I need a generic code to work for any Enum.

So far I found following way to compare, but I need a generic comparision statement as I don't know all Enums:

private static bool Compare<T>(T t1, T t2)
{
    if (t1 is IEnumerable<T>)
    {
        return (t1 as IEnumerable<T>).SequenceEqual(t2 as IEnumerable<T>);
    }
    else
    {
        Type[] genericTypes = t1.GetType().GetGenericArguments();
        if (genericTypes.Length > 0 && genericTypes[0].IsEnum)
        {
            if (genericTypes[0] == typeof(Days))
            {
                return (t1 as IEnumerable<Days>).SequenceEqual(t2 as IEnumerable<Days>);
            }
            else if (genericTypes[0] == typeof(Colors))
            {
                return (t1 as IEnumerable<Colors>).SequenceEqual(t2 as IEnumerable<Colors>);
            }
        }

        return false;
    }
}
Asim
  • 118
  • 6
  • Why do you need to test whether it's a list of enums specifically? Enums are value types, so you could just test for value types. – David Arno Jul 10 '15 at 09:33
  • @David, it is not Enums comparison, it is List of Enums comparison, which can't be compared like value types. – Asim Jul 10 '15 at 10:45
  • Then surely it's a list comparison problem? – David Arno Jul 10 '15 at 10:52
  • possible duplicate of [How do i get the difference in two lists in C#?](http://stackoverflow.com/questions/9840539/how-do-i-get-the-difference-in-two-lists-in-c) – David Arno Jul 10 '15 at 10:53

1 Answers1

3

First get the type of the generic arguments with Type.GetGenericArguments(), then you can call IsEnum on that.

So, something like

var listType = dict1[entry.Key].GetType();
if (listType.IsGenericType)
{
   var typeArguments = listType.GetGenericArguments();
   //if you only have List<T> in there, you can pull the first one
   var genericType = typeArguments[0];
   if (genericType.IsEnum) {
        // List elements matches...
   }                
} 

In answer to your comment, if you want to compare the 2 Lists, you can do the following. Because you have the lists as object in a dictionary, you're better of creating your own method to check whether each element is the same as the element in the other list, because for SequenceEqual you have to know the type.

        var listType = dict1[entry.Key].GetType();
        var secondListType = dict2[entry.Key].GetType();
        if (listType.IsGenericType && secondListType.IsGenericType)
        {
            //if you only have List<T> in there, you can pull the first one
            var genericType = listType.GetGenericArguments()[0];
            var secondGenericType = secondListType.GetGenericArguments()[0];
            if (genericType.IsEnum && genericType == secondGenericType && AreEqual((Ilist)dict1[entry.Key],(Ilist)dict2[entry.Key]))
            {                    
                // List elements matches...
            }
        }

    public bool AreEqual(IList first, IList second)
    {
        if (first.Count != second.Count)
        {
            return false;
        }

        for (var elementCounter = 0; elementCounter < first.Count; elementCounter++)
        {
            if (!first[elementCounter].Equals(second[elementCounter]))
            {
                return false;
            }
        }
        return true;
    } 
Stephen
  • 2,027
  • 2
  • 22
  • 26
  • I've already try it, but didn't find the way to match those List objects. If you know then please write the generic comparison statement. – Asim Jul 10 '15 at 09:52
  • @Asim I updated my answer to include the code to compare the 2 Lists – Stephen Jul 10 '15 at 10:08
  • Stephen: did you run ur code? It won't work as I already tried it. – Asim Jul 10 '15 at 10:40
  • @Asim: changed my answer, I didn't take into account you were working with `object` as type. Sorry about that. – Stephen Jul 10 '15 at 11:39