【问题标题】:can't use type stored in a type array不能使用存储在类型数组中的类型
【发布时间】:2018-03-28 20:46:08
【问题描述】:

我有一个叫做 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()

但这不起作用,有没有办法做到这一点?

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

【问题讨论】:

  • “不起作用”是什么意思?有什么错误吗?
  • options 包含类型,其中 Foo() 需要一个实例。
  • options[rnd.Next(options.Length)] as A 应该是 null 所以会抛出 NullReferenceException
  • @YeldarKurmangaliyev,它给出了这部分的转换错误: (options[rnd.Next(options.Length)] as A) "cannot convert from.... "

标签: c# inheritance types


【解决方案1】:

options 应该是 A-instances 的数组,而不是 Type[]

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

C# fiddle

【讨论】:

    【解决方案2】:

    您不能这样做,因为您的 options 数组包含类型本身,而不是实例。

    你可以做类似的事情

    Random rnd = new Random();
    var type = options[rnd.Next(options.Length)]
    var instance = Activator.CreateInstance(type) as A;
    instance.Foo();
    

    【讨论】:

      【解决方案3】:

      如果你想调用Foo你必须先创建一个实例,然后调用:

      ((options[rnd.Next(options.Length)].GetConstructor(new Type[0]).Invoke(null)) as A).Foo()
      

      【讨论】:

        【解决方案4】:

        其他答案已经描述了如何修复您的原始代码。

        但是,作为替代方案,您可以只使用 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;
        }
        

        【讨论】:

        • 谢谢,但我想避免 swtich statments,以获得更好的灵活性
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-05
        • 2021-08-09
        • 2019-07-29
        • 1970-01-01
        相关资源
        最近更新 更多