不能使用存储在类型数组中的类型

时间:2017-10-17 08:08:14

标签: c# inheritance types

我有一个名为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()

但这不起作用,有没有办法实现这个目标?

(顺便说一句,我没有这个名字,所以如果有人有更好的名字,他们可以随时编辑:))

4 个答案:

答案 0 :(得分:5)

options应该是A个 - 实例的数组,而不是Type[]

class Boo {
    public A[] options;
    public Boo() {
        options = new[] {
            new B(),
            new C(),
            new D(),
            new E()
        };
    }
}

C# fiddle

答案 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;
}