0

Say I get an answer to my other question and I can get all my objects, which implement BaseClass<StorageClassBase>, like this:

var t1 = myObjects.Where(o => o.GetType().HasBaseClassOf(typeof(BaseClass<>), typeof(StorageClassBase))).ToList();

How can I cast this list to List<BaseClass<StorageClassBase>>?


I tried the following, but it results in a list of null-s:

var res = t1.Select( x => x as BaseClass<StorageClassBase>).ToList();

For completeness sake:

  • BaseClass is a generic abstract class, which is implemented by the selected objects
  • StorageClassBase is also an abstract class. All the selected objects implement BaseClass with some specific implementation of StorageClassBase.
  • the extension function HasBaseClassOf checks, whether the Type inherits from BaseClass with generic type parameter StorageClassBase

Minimal reproducible example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MinimalReproducibleExample
{
public abstract class StorageClassBase
{
}

public class CoolStorageClass : StorageClassBase
{
}

public abstract class BaseClass<T> where T : StorageClassBase
{
}
public class CoolClass : BaseClass<CoolStorageClass>
{
}

public static class TypeExtensions
{
    //https://stackoverflow.com/a/457708
    public static bool HasBaseClassOf(this Type t, Type toCheck, Type genericParameter)
    {
        while ((t != null) && (t != typeof(object)))
        {
            var cur = t.IsGenericType ? t.GetGenericTypeDefinition() : t;
            if (toCheck == cur)
            {
                //also check whether the generic types match
                if (t.GenericTypeArguments[0].IsSubclassOf(genericParameter))
                {
                    return true;
                }
            }
            t = t.BaseType;
        }

        return false;
    }
}

class Program
{
    static void Main(string[] args)
    {
        List<object> myObjects = new List<object>();
        myObjects.Add(new CoolClass());
        myObjects.Add(new CoolClass());
        myObjects.Add(new object());
        myObjects.Add(new object());

        var t1 = myObjects.Where(o => o.GetType().HasBaseClassOf(typeof(BaseClass<>), typeof(StorageClassBase))).ToList();
        var t2 = t1.Select(o => o as BaseClass<StorageClassBase>).ToList();

        Console.ReadKey();

    }
}

}

G. B.
  • 528
  • 2
  • 15
  • 2
    The problem with both these questions, is they lack your actual problem. What problem are you trying to solve, why are you in this situation. If we could understand that, it may be easier to help you – TheGeneral Dec 16 '20 at 07:15
  • Say I have some classes, which do something (data acquisition in this case). This something is very similar for all the classes, therefore I extracted the common functionality in the abstract BaseClass. But, every class stores the data in a different storage class, which also have a common functionality, extracted to StorageClassBase. But there are classes, that are very different, and do not implement this interface. I have all the classes in a list, and need to select and use only those, which have this specific interface with the specific storage class. – G. B. Dec 16 '20 at 07:30
  • 1
    Just because two types exhibit a particular inheritance relationship, that does **not** mean that a generic type parameterised by those two types will exhibit the same inheritance relationship. A `BaseClass` is *not* derived from `BaseClass`. – Damien_The_Unbeliever Dec 16 '20 at 07:58
  • ooops, I did not know that... i need to find some way to get rid of the generic type argument then. – G. B. Dec 16 '20 at 08:01

0 Answers0