在for循环中为对象赋值

5
假设我有一个类为Character的对象MyCharacter,它具有以下属性:Health, Mana, MoveSpeed
从另一个方法中,我收到了一个字符串,其中包含这些状态,如下所示:
"Health: 100 Mana: 100 MoveSpeed: 100"
现在我想把这些状态分配给我的对象。我的当前尝试是这样的:
// stats is the string I showed above
var statsArray = stats.Split(' ');
for (var i = 0; i < statsArray.Length; i++)
{
    switch(statsArray[i])
    {
        default:
            break;
        case "Health:":
            MyCharacter.Health = statsArray[i+1];
            break;
        case "Mana:":
            MyCharacter.Mana = statsArray[i+1];
            break;
        case "MoveSpeed:":
            MyCharacter.MoveSpeed = statsArray[i+1];
            break;
    }
}

现在的问题是,我知道状态的顺序。它总是健康,然后法力值,最后是移动速度。因此,我正在寻找简化它的方法,即摆脱这个 switch(因为实际上这里的角色有 18 种状态,它不太好看)。
我的想法是通过数组并告诉程序将它找到的第一个数字分配给健康,第二个数字分配给法力和第三个数字分配给移动速度。
这种事情是否可能?

2
你现在对使用 switch case 有任何疑虑/性能/错误吗?为什么你想要改变?如果没有,对我来说,我更喜欢使用 switch case,因为它更容易调试和阅读。 - User2012384
如果您知道正确的顺序,为什么要首先使用标签?没有理由不使用例如100,100,100吗? - Luaan
你能够在不预先知道属性名称的情况下动态加载它们的唯一方法是使用反射(伴随着性能损耗和复杂度增加)。说实话,我认为现在的代码没有任何问题。任何傻瓜都可以写出计算机能理解的代码,好的程序员编写人类可读的代码 - Liam
如果stats是一个字符串,另一个选项是使用类似Json的字符串对象表示法,这样你就可以使你的“stringly typed object”更加明确。 - Liam
我寻找替代方案的主要原因,除了可能要摆脱我现在已有的大约150行代码之外,还有学习目的。这与性能无关。 - Wilsu
MyCharacter是一个对象,每当它被调用时就会被创建并返回。返回的对象随后被写入到List<Character>中。我只是不想让字符串解析成为Character类的一部分(例如在构造函数或其他地方),因为它应该只存储它的统计数据。 - Wilsu
4个回答

7
由于您已经知道确切的格式,因此可以直接访问索引:
string stats = "Health: 100 Mana: 100 MoveSpeed: 100";

var statsArray = stats.Split(' ');
MyCharacter.Health = statsArray[1];
MyCharacter.Mana = statsArray[3];
MyCharacter.MoveSpeed = statsArray[5];

您也可以使用正则表达式来实现此功能,这样有一个好处,它可以进一步验证您的模式(因此,如果存在不符合格式的情况,您会得到一个异常):
var m = Regex.Match(stats, @"Health: (\d+) Mana: (\d+) MoveSpeed: (\d+)");

MyCharacter.Health = m.Groups[1].Value;
MyCharacter.Mana = m.Groups[2].Value;
MyCharacter.MoveSpeed = m.Groups[3].Value;

注意:您可能希望这些属性包含整数,以便您可以计算这些值,因此您应该对每个值调用int.Parse()

我利用最后一天学习了正则表达式,真的太完美了,谢谢啊,伙计 :) - Wilsu

1

你可以使用字典。这将非常简单易懂。

Dictionary<string, int> dictionary =new Dictionary<string, int>();
dictionary.Add("health",100);
dictionary.Add("mana",100);
dictionary.Add("speed",40);

那么

mycharacter.Health=dictionary["health"];
mycharacter.Health=dictionary["mana"];
mycharacter.Health=dictionary["speed"];

这如何简化字符串解析?如果您已经使用另一种结构,为什么不直接将其放入字符对象中? - poke
你要如何设置字典?你需要自己添加值,而不是从字符串中获取,这也是OP遇到的问题。 - M.kazem Akhgary
好的,我没有注意到解析问题。 - Burak Karasoy

0

正则表达式是解析字符串的最佳方式。

请检查:

public class Character
{
    public int Health;
    public int Mana;
    public int MoveSpeed;

    public static Character FromString(string characterData)
    {
        MatchCollection matches = Regex.Matches(characterData, "[A-Za-z]+: ([\\d]+)");
        Character myCharacter = new Character();
        myCharacter.Health = Convert.ToInt32(matches[0].Groups[1].Value);
        myCharacter.Mana = Convert.ToInt32(matches[1].Groups[1].Value);
        myCharacter.MoveSpeed = Convert.ToInt32(matches[2].Groups[1].Value);
        return myCharacter;
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        Character myCharacter = Character.FromString("Health: 100 Mana: 110 MoveSpeed: 120");
    }
}

0

你可以在值之间加上空格或任何给定的字符作为分隔符。如果顺序始终相同,您将不会遇到问题。如果您从文件中读取字符串,则写入字符比以浮点数形式写入数据作为由浮点数组成的原始文件要低效得多。该文件将是sizeof(float)*18。您可以选择每个值的语义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接