Skimrande
Skimrande

Reputation: 831

C# dynamically instantiate Type from Enum

I am a C# beginner. I hope you have patience with me. Lets say I have an enum

public enum Dogs
{
    Terrier,
    Poodle,
    Pitbull,
}

and some dog classes

public class Terrier {
}

public class Poodle {
}

public class Pitbull {
}

And I for some reason want to instantiate each of the classes dynamically from their types (enum values),

        foreach(Dogs d in Enum.GetValues(typeof(Dogs)))
        {
            // d myDog = new d();
            // "...is a variable but is used like a type"
        }

I have also tried with

var myDog = Activator.CreateInstance(d);
// "...cannot convert from namespace.Dogs to System.Type"

Upvotes: 0

Views: 427

Answers (3)

Nyerguds
Nyerguds

Reputation: 5629

Don't use an enum for that. A much saner solution is an array of Types:

private static Type[] dogs =
{
    typeof(Terrier),
    typeof(Poodle),
    typeof(Pitbull),
}

Then you can still go over them all:

foreach (Type type in dogs)
{
    Object dog = Activator.CreateInstance(type);
}

Though unless you're only using .ToString() on it, you might want to give those classes a common interface or superclass to inherit (as rfmodulator also said in his answer) so you can actually call functions on the resulting objects. If all three inherit from a Dog superclass, which makes them share a common Bark() method, you can at least do something like this:

public abstract class Dog
{
    String Bark();
}

public class Terrier : Dog
{
    public override String Bark() { return "Woof!"; }
}

public class Poodle : Dog
{
    public override String Bark() { return "Yap"; }
}

public class Pitbull : Dog
{
    public override String Bark() { return "Whuff!"; }
}

...so you can actually get something useful out of your instantiated objects:

foreach (Type type in dogs)
{
    Dog dog = (Dog)Activator.CreateInstance(type);
    Console.WriteLine(dog.Bark());
}

The only slight downside to this method, from a design perspective, is that there's no way to enforce that only sub-types of Dog can be put in the Type[] dogs array; technically, any type object can be put in there. So that's the programmer's responsibility to not mess that up.

Upvotes: 2

progpow
progpow

Reputation: 1580

If you really want it:

(typeof(Dogs)).Assembly.CreateInstance(d.ToString());

Upvotes: 4

rfmodulator
rfmodulator

Reputation: 3738

Dogs.Terrier is a different thing than Terrier.

Here is how you could do something like you're describing:

For simplicity, I'm going to make all the classes implement a common interface, IDog:

public interface IDog { }

public class Terrier : IDog
{
}

public class Poodle : IDog
{
}

public class Pitbull : IDog
{
}

Now we can do this:

IDog dog;
foreach (Dogs d in Enum.GetValues(typeof(Dogs)))
{
    switch (d)
    {
        case Dogs.Terrier:
            dog = new Terrier();
            break;
        case Dogs.Poodle:
            dog = new Poodle();
            break;
        case Dogs.Pitbull:
            dog = new Pitbull();
            break;
        default:
            throw new Exception("no such dog!");
    }

    Debug.WriteLine($"dog is {dog.GetType()}");
}

Upvotes: 1

Related Questions