Search code examples
c#genericsinterfacemarker-interfaces

Alternative to using Marker Interfaces to test for derived generic classes?


I have an application that uses many types of derived classes from a common base class, and several of the derived classes use generics. The application often needs to iterate through collections of the derived classes and identify specific class types for special processing.

The problem is how to test for a specific generic derivative of a base class without knowing the type, in a concise and elegant way ( since it is done often in the project ) ?

The 'is' operator won't work for this:

if (item is MyDerivedGenericClass<>)  // Won't compile

To work around this problem, I am considering using empty Marker Interfaces to identify the special classes within a collection. This seems to be the cleanest solution.

A couple of notes:

  • This is a closed project, and will not be a commercially distributed library.
  • Classes that are tagged by a Marker Interface are being tagged as a permanent unique type, and all derived classes from that type would correctly inherit the Marker.

An example below:

public interface MarkerA { }  // Empty Interface
public interface MarkerB { }  // Empty Interface
public interface MarkerC { }  // Empty Interface

public class BaseClass { }

public class DerivedClassA : BaseClass { }
public class DerivedClassB : BaseClass { }
public class DerivedClassC : BaseClass { }

public class DerivedSpecialClass : BaseClass { }

public class DerivedSpecialA : DerivedSpecialClass { }
public class DerivedSpecialB : DerivedSpecialClass { }
public class DerivedSpecialC : DerivedSpecialClass { }

public class DerivedSpecialGenericA<T> : DerivedSpecialClass, MarkerA { }
public class DerivedSpecialGenericB<T> : DerivedSpecialClass, MarkerB { }
public class DerivedSpecialGenericC<T> : DerivedSpecialClass, MarkerC { }


public void ProcessClasses(List<BaseClass> list)
    {
        // Iterate through a list of mixed classes that all derive from BaseClass
        foreach (BaseClass item in list)
        {

            // Ideal approach, but doesn't compile:

            // Try to isolate select class types to do something interesting with
            if ((item is DerivedSpecialA) || (item is DerivedSpecialB) || (item is DerivedSpecialGenericB<>))
            {
                var specialItem = item as DerivedSpecialClass;

                DoSomethingInteresting(specialItem);

                Console.WriteLine(specialItem.Title);
            }


            // Alternative workaround that tests for the Marker instead

            // Try to isolate select class types to do something interesting with
            if ((item is DerivedSpecialA) || (item is DerivedSpecialB ) || (item is MarkerB))
            {
                var specialItem = item as DerivedSpecialClass;

                DoSomethingInteresting(specialItem);

                Console.WriteLine(specialItem.Title);
            }
        }
    }

Does anyone have any better ideas for how to approach this problem ?

Thanks.


Solution

  • When I need to write code that differs depending on the type of object, and that code is not practical as a virtual method, I use an identifier implemented as a virtual property returning immutable information. This is cleaner, and uses no additional instance storage, although it would be nice to initialize MarkerType via a type parameter.

    public class BaseClass 
    {
        public abstract MarkerType { get; }  
    }
    
    public enum MarkerType { A, B, C }