DEV Community

Discussion on: Casting stinks. Generic classes are worse.

610yesnolovely profile image
Harvey Thompson • Edited on

I know this is in C#, but if this were general question for some abstract language then the problem might be solved with what Scala calls Abstract Types (I think it's better to call them Abstract Member Types).

If you just want to solve it in C#, read no further in my post, because this is of no help (sorry about that).

Otherwise see:

The idea is to move the types from generic parameters to abstract (member) types:

public abstract class VehicleAssemblyLine
  public abstract type E : Engineer;                    // Totally made up C# syntax, WILL NOT COMPILE
  public abstract type I : VehicleAssemblyLineInstructions;
  public abstract type V : Vehicle; 

  public E LeadEngineer { get; set; }
  public abstract V Build(I instructions);

What this means is that sub-classes of VehicleAssemblyLine have to provide three type definitions of E, I and V that must sub-class described.

This at first does not seem to be that much different than providing them as generic arguments, but when you sub-class it makes more sense:

public class Sedan : Vehicle
  public override type E = SedanEngineer; // C# made up syntax, IT NO COMPILE
  public override type I = SedanAssemblyLineInstructions;
  public override type V = Sedan;

The idea is that Sedan provides a more concrete definition of type E, so all the inherited methods of Sedan from Vehicle return the more specific type. It essentially moves the parameterization from the declaration site into the body. This reduces all the generic arguments and reduces exponential growth of generic parameters.

For example, you can still refer to a VehicleFactory without all the generic arguments, and if required you can do safe casting to SedanFactory or others as required.

(If this were C++ you might be able to use type traits to simulate all of this).

I'm not sure what other languages have abstract member types? Possibly Swift's associated types are a similar thing?

Perhaps C# and other languages will adopt this feature in later releases. Until then simulating it in C# means using generics and lots of casting and typing. Ugh.