Reputation: 591
I have a base class called a, and it has a virtual function called Foo
class a
{
public virtual void Foo() {}
}
And i have a bunch of other classes inheriting from it.
class B : A{}
class C : A{}
class D : A{}
class E : A{}
Now, i want to have an array of the types so i can choose one by random so i tried this:
class Boo
{
Type[] options;
public Boo()
{
options = new[]
{
typeof(B),
typeof(C),
typeof(D),
typeof(E)
};
}
}
And then i want to choose one at random and use its Foo method and i did it like this:
Random rnd = new Random();
(options[rnd.Next(options.Length)] as A).Foo()
But this doesn't work, is there any way of accomplishing this?
(Btw, i didn't have a good name for this so if anyone has a better name they can feel free to edit :) )
Upvotes: 2
Views: 90
Reputation: 9463
options
should be an array of A
-instances, not a Type[]
.
class Boo {
public A[] options;
public Boo() {
options = new[] {
new B(),
new C(),
new D(),
new E()
};
}
}
Upvotes: 5
Reputation: 109567
Other answers have already described how to fix your original code.
However, as an alternative, you could just use a switch statement or similar approach:
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!");
}
}
Or if you want to use reflection to choose randomly from all types that inherit from class A
(that are defined in the same assembly as 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;
}
Upvotes: 0
Reputation: 4219
If you want to invoke Foo
you have to create an instance first, then invoke:
((options[rnd.Next(options.Length)].GetConstructor(new Type[0]).Invoke(null)) as A).Foo()
Upvotes: 0
Reputation: 1847
You cannot do that because your options
array holds the types themselves, not instances.
You can do something like
Random rnd = new Random();
var type = options[rnd.Next(options.Length)]
var instance = Activator.CreateInstance(type) as A;
instance.Foo();
Upvotes: 1