C# 在C中返回一个随机类型的对象#

C# 在C中返回一个随机类型的对象#,c#,C#,我有一个工厂类,我希望它能够返回一个随机类型的对象。应从预定义的类型列表中选择类型。 比如说: public class NeutralFactory : NPCFactory { private List<Type> humanoids = new List<Type> { typeof(Dwarf), typeof(Fairy), typeof(Elf), typeof(Troll), typeof(Orc) }; pr

我有一个工厂类,我希望它能够返回一个随机类型的对象。应从预定义的类型列表中选择类型。 比如说:

    public class NeutralFactory : NPCFactory
    {
        private List<Type> humanoids = new List<Type> { typeof(Dwarf), typeof(Fairy), typeof(Elf), typeof(Troll), typeof(Orc) };
        private Random random = new Random();
        public Creature CreateHumanoid(int hp = 100)
        {
            int index = random.Next(humanoids.Count);
            return new humanoids[index]();
        }
    }
但我并不真的喜欢它。有更好的方法吗

编辑:
以下是我最终使用的:

        private List<Func<int, string, Creature>> humanoids = new List<Func<int, string, Creature>> {
            (hp, name) => new Fairy(hp, name),
            (hp, name) => new Troll(hp, name),
        };

        private List<Func<int, Creature>> animals = new List<Func<int, Creature>> {

            (hp) => new Wolf(hp)
        };

        public override Creature CreateHumanoid(int hp = 100, string name = null)
        {
            int index = random.Next(humanoids.Count);
            return humanoids[index](hp, name);
        }

        public override Creature CreateAnimal(int hp = 100)
        {
            int index = random.Next(animals.Count);
            return animals[index](hp);
        }
private List humanoids=新列表{
(hp,名称)=>新仙女(hp,名称),
(hp,名称)=>新巨魔(hp,名称),
};
私有列表动物=新列表{
(hp)=>新狼(hp)
};
公共覆盖生物CreateHumanoid(int hp=100,字符串名称=null)
{
int index=random.Next(humanoids.Count);
返回类人形[索引](hp,名称);
}
公共覆盖生物CreateAnimal(智力生命=100)
{
int index=random.Next(动物数);
返回动物[指数](hp);
}
我在使用
()=>function()
语法的地方发现了类似的问题,但我不理解,我猜这些是某种特殊的委托? 不管怎么说,它可以按照我的要求工作,而且非常简洁

对于未来的读者,这里有一个关于Func的有用MSDN页面:

您可以在列表中创建函数

public class NeutralFactory: NPCFactory
    {
        private List<Func<int, Creature>> humanoids = new List<Func<int, Creature>> {
            hp=> new Dwarf(hp),
            hp=> new Fairy(hp),
            hp=> new Elf(hp),
            hp=> new Troll(hp),
            hp=> new Orc(hp)
        };
        private Random random = new Random();

        public Creature CreateHumanoid(int hp = 100)
        {
            int index = random.Next(humanoids.Count);
            return humanoids[index](hp);
        }
    }
公共类中立工厂:NPC工厂
{
私有列表类人=新列表{
hp=>新矮星(hp),
hp=>新精灵(hp),
hp=>新Elf(hp),
hp=>新巨魔(hp),
hp=>新Orc(hp)
};
私有随机=新随机();
公共生物CreateHumanoid(智力生命=100)
{
int index=random.Next(humanoids.Count);
返回类人[索引](hp);
}
}

为了避免为每个类编写创建函数,您可以使用
Activator.CreateInstance

使用系统;
使用System.Collections.Generic;
名称空间so60998181
{
公营动物
{
公共int hp;
公共生物()
{
这是1.hp=100;
}
公共生物(智力hp)
{
this.hp=hp;
}
公共重写字符串ToString()
{
返回String.Format(“{0},{1}hp”,GetType().Name,hp);
}
}
公共级矮人:生物
{
公共矮星(int hp):基(hp){}
}
公共类精灵:生物
{
公共精灵(智力hp):基础(hp/3){}
}
公共类兽人:生物
{
公共兽人(智力生命):基础(生命*4){}
}
班级计划
{
私有静态列表类人=新列表{typeof(矮人)、typeof(仙女)、typeof(兽人)};
私有静态随机rng=新随机();
私人静态生物CreateHumanoid(智力hp=100)
{
int index=rng.Next(humanoids.Count);
var params=新对象[]{hp};
返回Activator.CreateInstance(t,类人[index],null,params,null)作为生物;
}
静态void Main(字符串[]参数)
{
对于(变量i=0;i<10;i++)
{
Console.WriteLine(CreateHumanoid(i*10));
}
}
}
}
这将输出例如

Fairy, 0 hp
Orc, 40 hp
Fairy, 6 hp
Orc, 120 hp
Fairy, 13 hp
Orc, 200 hp
Fairy, 20 hp
Fairy, 23 hp
Fairy, 26 hp
Fairy, 30 hp

(可怜的仙女#1)

您可以使用方法
GetConstructor(type[])
获取构造函数,该构造函数很可能是
Func
对象。如果使用
Invoke
方法,则会返回一个对象。最后,您必须将其解析为生物以返回它

public Creature CreateHumanoid( int hp = 100 ) {
        int index = random.Next( humanoids.Count );
        Type t = humanoids[index];
        return (Creature) t.GetConstructor( new Type[] { typeof( int ) } ).Invoke( new object[] { hp } );
    }

听起来像是一个抽象类的好例子。如果你不希望某人只创建“生物”的一个实例,相反,他们应该总是创建一个生物的版本,那么你需要一个抽象类。所以你可以这样做:

public class NeutralFactory : NPCFactory
{
    private Random random = new Random();

    private List<Func<int, Creature>> humanoids = new List<Func<int, Creature>> {
        hp=> new Dwarf(hp),
        hp=> new Fairy(hp),
        hp=> new Elf(hp),
        hp=> new Troll(hp),
        hp=> new Orc(hp)
    };

    public Creature CreateHumanoid(int hp)
    {
        int index = random.Next(humanoids.Count);
        return humanoids[index](hp);
    }
}

public abstract class Creature
{
    public int hp { get; set; }

    public Creature(int hp)
    {
        this.hp = hp;
    }
}
public class Orc : Creature
{
    public Orc(int hp) : base(hp) { }
}
更新


在create方法之外添加了“人形”以避免每次都创建对象列表。使用Func列表取自OxQ,尽管使用这样一个抽象类的目的是为了确保某人不能只实例化“biosure”,你也可以使用它来创建基本功能

我想我更喜欢switch语句。易于阅读和理解正在发生的事情。然而,如果你真的打算使用类型列表
return(biecast)Activator.CreateInstance(humanoids[index],hp)应该很容易工作。但这不是问题。OP清楚地说明了开关按预期工作,他只是不“喜欢”它。这是我在类似问题中看到的,但没有任何参数或返回类型。我不熟悉这个(argument1,argument2)=>new Object(argument1,argument2)语句,我将编辑这个问题,以便将来的读者不会像我一样感到困惑。若我错了,请纠正我,但这看起来是一个糟糕的解决方案,您创建每种类型的对象并返回其中一个。我猜那些未使用的会在某个时候被垃圾收集器抓取,但它仍然会产生不必要的开销。@Harvastum-如果你指的是创建一个人形列表,那么它与OP最初所做的是一致的,并且不是问题的主要焦点。此外,这里的每个答案都有相似之处。你需要一份人形机器人的名单来挑选。我相信可以使用另一种方法,但是创建这样的列表的成本很低。但是在
CreateHumanoid
的每次调用中都会创建一个对象列表!我最初提出了工厂每个实例的类型列表,但老实说,这可能是一个静态列表。如果类很大和/或列表很长,那么在每次调用中创建一个对象列表(只丢弃一个对象)的成本可能非常大。另外,没有其他答案建议创建每种类型的对象,它们只是显示了调用特定构造函数的不同方式。@Harvastum-upd
public class Orc : Creature
{
    public Orc(int hp) : base(hp) { }
}