Steven Scott
Steven Scott

Reputation: 11250

c# runtime polymorphism with abstract base class

I am trying to clean up an existing code base, and am having trouble with using a generic reference name to the different derived classes of an abstract class.

For instance:

public abstract class Base<T> : Utilities.CommonRequiredObject
{
    protected List<T> RawContents = new List<T>();
    .
    .

    public abstract void LoadContents(List<T> Contents);        // Each Class needs to load and process differently
    protected List<T> Contents;

    public virtual void DoSomething()           // Default here for common use. Defined in Each class for its specifics (if needed)
    {
    ...
    }
    public abstract List<T> FunctionToGetContents();

}

public class FOO : Base<string>
{
    public override void DoSomething() ...
    public override List<string> FunctionToGetContents() ...
}

public class BAR : Base<byte>
{
    public override void DoSomething() ...
    public override List<byte> FunctionToGetContents() ...
}

Main Logic to try to use common variable. I want to create a new class to use, but want to use it then in a runtime polymorphic way. As the classes have the common functionality, and have overrides where needed, I want to be able to create an instance, and then use it:

IE: Base<T> ObjectToUse;

This way, I can simply refer to the ObjectToUse in the following code and call common methods. As I inherited some common routines from another base class, I am not sure if I can use an interface or not.

if(variable)
{
    FOO ObjectToUse = new FOO();
}
else
{
    BAR ObjectToUse = new BAR();
}

ObjectToUse.LoadContents(ObjectToUse.FunctionToGetContents());
ObjectToUse.DoSomething();
...

Edit: Based on the comments I received quickly (thanks again everyone) would it be better than to remove the Generic (Base<T>) and have the classes all of type Base(), then I could define the ObjectToUse simply as Base ObjectToUse; I believe.

Upvotes: 2

Views: 1485

Answers (1)

BradleyDotNET
BradleyDotNET

Reputation: 61369

This cannot be done.

By utilizing a reference that requires a generic type parameter, you must give it one. You could utilize dynamic here so that the type is run-time evaluated, but thats the best you will get.

Even utilizing something like a template method pattern, you would need to specify the generic type argument. If you just want the DoSomething method for this, it would need to be promoted to a higher base class (or an interface) so you could hold a reference to that type, and call that (non-generic) function.

To your comment, the solution I would take is this; refactor the common code into a template method pattern within the base class. Then have the "triggering" function be a non-generic inherited member from a non-generic base class (or interface). Now, you can hold a reference to that type, and invoke the template method to cause the other calls to occur.

public void DoAwesomeStuff() //inherited from non-generic parent or interface
{
   LoadContents(FunctionToGetContents());
   DoSomething();
}

Then:

IDoesAwesomeStuff ObjectToUse = new FOO();
ObjectToUse.DoAwesomeStuff();

Upvotes: 4

Related Questions