C# 从 Enum 动态实例化 Type

C# dynamically instantiate Type from Enum

我是 C# 初学者。我希望你对我有耐心。假设我有一个枚举

public enum Dogs
{
    Terrier,
    Poodle,
    Pitbull,
}

还有一些狗类

public class Terrier {
}

public class Poodle {
}

public class Pitbull {
}

出于某种原因,我想根据它们的类型(枚举值)动态实例化每个 类,

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

我也试过

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

Dogs.TerrierTerrier 不同。

您可以按照以下方式执行您描述的操作:

为简单起见,我将让所有 类 实现一个通用接口,IDog:

public interface IDog { }

public class Terrier : IDog
{
}

public class Poodle : IDog
{
}

public class Pitbull : IDog
{
}

现在我们可以这样做了:

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()}");
}

如果你真的想要它:

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

不要为此使用枚举。一个更明智的解决方案是类型数组:

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

那你还可以全部复习一下:

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

尽管除非你只在上面使用 .ToString(),否则你可能想给那些 类 一个公共接口或超类来继承(正如 rfmodulator 在他的回答中所说)这样你就可以实际上在结果对象上调用函数。如果这三个都继承自一个 Dog 超类,这使得它们共享一个共同的 Bark() 方法,您至少可以这样做:

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!"; }
}

...因此您实际上可以从实例化对象中获得一些有用的东西:

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

从设计的角度来看,此方法唯一的小缺点是无法强制只能将 Dog 的子类型放入 Type[] dogs 数组;从技术上讲,任何类型的对象都可以放在那里。所以程序员有责任不要把事情搞砸。