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