我有一个名为a的基类,它有一个名为Foo的虚函数
class a
{
public virtual void Foo() {}
}
我还有很多继承自它的其他类。
class B : A{}
class C : A{}
class D : A{}
class E : A{}
现在,我希望有一个类型的数组,所以我可以随机选择一个,所以我尝试了这个:
class Boo
{
Type[] options;
public Boo()
{
options = new[]
{
typeof(B),
typeof(C),
typeof(D),
typeof(E)
};
}
}
然后我想随机选择一个并使用它的Foo方法,我这样做:
Random rnd = new Random();
(options[rnd.Next(options.Length)] as A).Foo()
但这不起作用,有没有办法实现这个目标?
(顺便说一句,我没有这个名字,所以如果有人有更好的名字,他们可以随时编辑:))
答案 0 :(得分:5)
options
应该是A
个 - 实例的数组,而不是Type[]
。
class Boo {
public A[] options;
public Boo() {
options = new[] {
new B(),
new C(),
new D(),
new E()
};
}
}
答案 1 :(得分:1)
您不能这样做,因为您的options
数组本身包含类型,而不是实例。
您可以执行类似
的操作Random rnd = new Random();
var type = options[rnd.Next(options.Length)]
var instance = Activator.CreateInstance(type) as A;
instance.Foo();
答案 2 :(得分:0)
如果要调用Foo
,则必须先创建实例,然后调用:
((options[rnd.Next(options.Length)].GetConstructor(new Type[0]).Invoke(null)) as A).Foo()
答案 3 :(得分:0)
其他答案已经描述了如何修复原始代码。
但是,作为替代方案,您可以使用switch语句或类似方法:
public static A RandomlyCreateA(Random rng)
{
switch (rng.Next(4))
{
case 0: return new B();
case 1: return new C();
case 2: return new D();
case 3: return new E();
default: throw new InvalidOperationException("Can't happen!");
}
}
或者,如果您想使用反射从所有继承自class A
的类型中随机选择(在与class A
相同的程序集中定义):
public static A RandomlyCreateA(Random rng)
{
var types = Assembly.GetAssembly(typeof(A)).GetTypes().Where(t => t.IsSubclassOf(typeof(A))).ToArray();
return Activator.CreateInstance(types[rng.Next(types.Length)]) as A;
}