1

Apologies for the awful title, I couldn't think of a better way to phrase it.

Essentially I have an abstract base class Category and whole host of derived classes inheriting from that. Is it possible to do something along the lines of:

List<Category> catList = new List<Category>();
catList.Add(new Category(myCategoryTypeString));

Where myCategoryTypeString will always be the name of one of the derived classes and have it instead create a new object of that derived class (presumably using a switch on the string to determine which class to use).

So that something along the lines of:

catList.Add(new Category("Engineering"));

Would add a new object of Engineering : Category type to the list?

If that is possible how would one go about doing this? My abstract class is defined thusly:

abstract class Category
{
    private string line;
    private bool ToChallenge;
    private string[] columns;
    private int oppLevel;

    protected Category(string line)
    {
        this.line = line;
        columns = line.Split(',');
    }

    public abstract bool IsAnomoly();
    public abstract void CategoriseAnomoly();
    public abstract void WriteLine();

}
ScottishTapWater
  • 3,656
  • 4
  • 38
  • 81
  • 3
    It *is* possible, but your approach is indicative of a code smell. Are you sure you want to use a late binding approach here? You lose the benefits of compile-time checking, and you're leaving it open to errors. – rory.ap Nov 18 '16 at 14:11
  • It's not entirely necessary if I'm honest, I was just wondering if it was possible more than anything – ScottishTapWater Nov 18 '16 at 14:14
  • This should not have been closed so fast. Im pretty sure that there is a solution with generics that won´t have anything to do with "Converting string to a class name". – Udontknow Nov 18 '16 at 14:19
  • I've found a solution using `Activator.CreateInstance()` but I can't add it because this has been closed, I probably shouldn't have allowed it to be closed. – ScottishTapWater Nov 18 '16 at 14:47

1 Answers1

5

No, you can't do that - if you call new Foo(), that will always create an instance of Foo, never of a subclass.

Instead, create a static factory method in Category:

public static Category CreateCategory(string line)
{
    if (line == "Engineering")
    {
        return new EngineeringCategory();
    }
    // Whatever you want to do for non-engineering categories
}

As noted in comments, using the actual type name probably isn't a great idea, unless this is already machine-generated output. If you really want to, you can use something like:

public static Category CreateCategory(string typeName)
{
    // Note that the type name would have to be namespace-qualified here
    Type type = Type.GetType(typeName);
    return (Category) Activator.CreateInstance(type);
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194