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.Terrier
与 Terrier
不同。
您可以按照以下方式执行您描述的操作:
为简单起见,我将让所有 类 实现一个通用接口,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
数组;从技术上讲,任何类型的对象都可以放在那里。所以程序员有责任不要把事情搞砸。
我是 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.Terrier
与 Terrier
不同。
您可以按照以下方式执行您描述的操作:
为简单起见,我将让所有 类 实现一个通用接口,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
数组;从技术上讲,任何类型的对象都可以放在那里。所以程序员有责任不要把事情搞砸。