我有一个名为武器的课程,它存储名为力量,敏捷,活力,智力的公共领域。 (输入Int32)
在武器对象的构造函数中,我有一个方法可以随机选择其中一个属性'并为其赋值。
Random random = new Random();
int primary = random.Next(0, 4);
if (//Condition met)
{
switch (primary)
{
case 0:
Strength = ...
break;
case 1:
Dexterity = ...
break;
case 2:
Vitality = ...
break;
case 3:
Intelligence = ...
break;
}
}
我觉得这段代码难看并难以维护。
有没有办法存储这些'属性'在数组或列表中?然后,Random将在0和Attributes.Length之间进行选择,并相应地分配一个值。
有点像这样(这不会让你理解)
Random random = new Random();
int[] attributes = {this.Strength, this.Dexterity, this.Vitality, this.Intelligence};
int index = random.Next(0, attributes.Length);
//lets say 0, so index = Strength
if (//Condition met)
{
//This is the part where index would be 0 so the program would assign 'Strength' a value
}
该值应分配给Array中选择的字段。不是数组中的元素。
这在以后开发继承类
时会有很大帮助答案 0 :(得分:2)
可以使用unsafe
代码和指针完成,但更安全的方法可以使用多种方法:
Action<int>[] stats = { i => Strength = i, i => Dexterity = i, i => Vitality = i, i => Intelligence = i };
stats[new Random().Next(stats.Length)](123); // set random stat to 123
答案 1 :(得分:1)
我建议你使用Hashmap。你可以通过put和get方法避免多个switch和case语句。
答案 2 :(得分:1)
您可以使用enum。
enum Attributes {Strength, Dexterity, Vitality, Intelligence};
然后你可以switch
:
switch (chosenAttribute)
{
case Attributes.Strength:
...
break;
case Attributes.Dexterity:
...
break;
case Attributes.Vitality:
...
break;
case Attributes.Intelligence:
...
break;
}
答案 3 :(得分:1)
有不同的解决方法。 例如,您可以将所有属性包装到某个类中,如下所示,并使您的属性包围它:
public class ItemAttribute
{
public int Value { get; set; }
}
public class Weapon
{
private readonly ItemAttribute _strengthAttribute = new ItemAttribute();
// ....
private readonly ItemAttribute[] _attributes = new[] {_strengthAtribute};
public int Strength
{
get { return _strengthAttribute.Value; }
set { _strengthAttribute.Value = value; }
}
}
在这种情况下,您可以使用一些额外的逻辑(例如处理最小/最大值)扩展您的属性。它被称为&#34;价值对象&#34;图案。
直接存储int
值的集合(数组或字典 - 它并不重要)的另一种方法。并且还创建包装器属性。
答案 4 :(得分:1)
你有很多可能性,但你应该考虑哪一种最适合你的问题。假设您有一个基类用于所有项目:
public abstract class BaseItem {
// from this class other items derive
}
如果是这种情况,那么您可以创建简单的“地图”,将属性与某种“名称”连接起来。你可以在启动时做一次:
public abstract class BaseItem {
static Dictionary<string, PropertyInfo> _attributes = null;
public BaseItem() {
if ( _attributes == null ) {
InitializeProperties();
}
}
void InitializeProperties() {
_attributes = new Dictionary<string, PropertyInfo>()
var properties = typeof(BaseItem).GetProperties().Where( property => Attribute.IsDefined(property, typeof(ItemAttributeAttribute)));
foreach(var property in properties) {
string name = ((ItemAttributeAttribute)property.GetCustomAttribute(property, typeof(ItemAttributeAttribute))).AttributeName;
_attributes.Add(name, property);
}
}
}
现在您可以添加此自定义属性ItemAttributeAttribute
public ItemAttributeAttribute : Attribute { string _Name; public string AttributeName { get { return _Name; } set { _Name = value; } } public ItemAttributeAttribute(string name) { _Name = name; } }
最后要做的是用名称绑定属性:
public abstract class BaseItem {
// rest of code here ...
[ItemAttribute("Agility")]
int Agility;
// rest of code here ...
}
这样,您可以轻松地将属性“绑定”到名称。现在您可以使用一些方法来分配值:
void SetValue(string name, object value) {
if(_attributes.ContainsKey(name)) {
_attributes[name].SetValue(this, value); // you can put this into BaseItem though
}
}
使用您展示的示例,我将制作2个课程Sword
和Shield
,我会用随机值填充它们:
public class Sword : BaseItem {
public Sword() : base() {
string[] names = new string[] { "atk", "def", "weight", "something" };
string choosen = names[new Random().Next() % names.Length];
SetValue(choosen, new Random().Next() % 1337);
}
}
public class Shield : BaseItem {
public Shield() : base() {
int rand = new Random().Next() % _attributes.Count();
SetValue(_attributes.Keys[rand], new Random().Next() % 1337);
}
}
当然,您必须记住在基类中设置所有属性,这可能是困难的,但您也可以对此方法进行一些改进。
对于所有Reflection
仇恨者(我知道大多数SO用户都是这样):有时候最好使用这种方法,而不是制作无用的变量,方法和代码行的负载。