Search code examples
c#listgenericscastingsubtype

calling method with list of subtype without casting


The Call

List<SubClazz> subList1 = new List<SubClazz>();
List<SubClazz> subList2 = new List<SubClazz>();
FuzzyCompareCollection(subList1,subList2); //Compile Error 

How i could do it

FuzzyCompareCollection(subList1.Cast<SuperClazz>().ToList(),subList2.Cast<SuperClazz>().ToList()); 

Method Definition

public static bool FuzzyCompareCollection<T>(List<T> list1, List<T> list2) where T : SuperClazz
    {
        if (list1.Count != list2.Count)
        {
            return false;
        }
        Dictionary<string, SuperClazz> dict1 = new Dictionary<string, SuperClazz>();
        Dictionary<string, SuperClazz> dict2 = new Dictionary<string, SuperClazz>();
        foreach (T item in list1)
        {
            dict1[item.ID] = item; //ID is an attribute of SuperClazz
        }
        foreach (T item in list2)
        {
            dict2[item.ID] = item;
        }

        bool equals = true;
        foreach (string key in dict1.Keys)
        {
            try
            {
                equals = Util.ReflectiveEquals(dict1[key], dict2[key]);
                if (!equals)
                {
                    break;
                }
            }
            catch (KeyNotFoundException e)
            {
                return false;
            }
        }
        return equals;
    }

I think i should be able to call the method without casting it so SuperClazz since the Lists contain SubTypes of SuperClazz. But Is there a way? Or is it really not possible and if there is no way could you explain to me why this can't work?


Solution

  • You need to make the FuzzyCompareCollection method to take parameters of type IReadonlyList<T> instead of List<T>. This will work because in contrast to List<T>, IReadonlyList<T> is covariant. This means that given Sub is a subtype of Super, IReadonlyList<Sub> is a subtype of IReadonlyList<Super> where as List<Sub> is NOT a subclass of List<Super>.