【问题标题】:Get specific values of a struct/List获取结构/列表的特定值
【发布时间】:2023-03-12 23:13:01
【问题描述】:

我正在使用 Unity3D + C# 创建游戏。

我现在得到的是:一个 SQL 数据表,由 8 列组成,总共包含 3 个条目,以及一个包含每个条目的列表“_WeapList”(如下所示)。

public struct data
{
    public string Name;
    public int ID, dmg, range, magazin, startammo;
    public float tbtwb, rltimer;
}

List<data> _WeapList;
public Dictionary<int, data>_WeapoList; //probable change    

[...]

//reading the SQL Table + parse it into a new List-entry
while (rdr.Read())
    {
        data itm = new data();

        itm.Name = rdr["Name"].ToString();
        itm.ID = int.Parse (rdr["ID"].ToString());
        itm.dmg = int.Parse (rdr["dmg"].ToString());
        itm.range = int.Parse (rdr["range"].ToString());
        itm.magazin = int.Parse (rdr["magazin"].ToString());
        itm.startammo = int.Parse (rdr["startammo"].ToString());
        itm.tbtwb = float.Parse(rdr["tbtwb"].ToString());
        itm.rltimer = float.Parse(rdr["rltimer"].ToString());

        _WeapList.Add(itm);
        _WeapoList.Add(itm.ID, itm);//probable change
    }

现在我想创建一个“武器”类,它具有相同的 8 个字段,并通过给定的 ID 输入它们

如何提取列表/结构中特定项(由 int ID 确定,始终唯一)的值?

public class Weapons : MonoBehaviour 
{

    public string _Name;
    public int _ID, _dmg, _range, _magazin, _startammo;
    public float _tbtwb, _rltimer;

    void Start()
    {//Heres the main problem
        _Name = _WeapoList...?
        _dmg = _WeapoList...?
    }
}

【问题讨论】:

  • 如果您要经常进行这些查找,为什么不使用字典而不是列表呢?类似于Dictionary&lt;int, data&gt; _WeapList,索引是武器的ID。然后你可以用_WeapList[weaponID]访问它,它会比使用循环/LINQ搜索列表快很多。
  • 您可能想重新考虑使用可变结构。我建议要么将其设为一个类(使用属性而不是公共字段),要么通过添加一个设置私有字段并公开只读属性的构造函数来使结构不可变。 stackoverflow.com/questions/441309/why-are-mutable-structs-evil
  • 首先:谢谢,我以前从未使用过 LINQ 表达式,尽管我也会重新考虑结构问题。尽管如此,我不明白如何输入字典,也不知道如何找到例如 ID 为“3”的武器的 int dmg。我创建了一个字典并将这个“_WeapoList.Add(itm.ID, itm);”进入 while(rdr.Read()){ ... }。我如何将“dmg”值解析为我的武器类? dmg = 数据库._WeapList[ ??? ](我已将这些更改放入上面的代码中)
  • @Csharpest 你从_WeapList[weaponID] 得到一个data 对象。所以要访问它的任何成员,只需使用. 语法,例如。 _WeapList[weaponID].dmg.
  • @Programmer 我想首先确定 OP 出于某种原因并不反对使用 Dictionary - 因为听起来他正在考虑它,我想我很快就会把它作为答案。跨度>

标签: c# list unity3d struct


【解决方案1】:

如果您的武器收藏可能变得非常大,或者您需要经常在其中查找武器,我建议为此使用字典而不是列表(使用武器 ID 作为键)。查找 will be much quicker using a Dictionary key 而不是使用循环或 LINQ 搜索列表。

您可以通过如下方式修改代码来做到这一点:

public Dictionary<int, data>_WeapList;

[...]

//reading the SQL Table + parse it into a new List-entry
while (rdr.Read())
{
    data itm = new data();

    itm.Name = rdr["Name"].ToString();
    itm.ID = int.Parse (rdr["ID"].ToString());
    itm.dmg = int.Parse (rdr["dmg"].ToString());
    itm.range = int.Parse (rdr["range"].ToString());
    itm.magazin = int.Parse (rdr["magazin"].ToString());
    itm.startammo = int.Parse (rdr["startammo"].ToString());
    itm.tbtwb = float.Parse(rdr["tbtwb"].ToString());
    itm.rltimer = float.Parse(rdr["rltimer"].ToString());

    _WeapList.Add(itm.ID, itm);//probable change
}

然后,要访问列表中的元素,只需使用以下语法:

_WeapList[weaponID].dmg; // To access the damage of the weapon with the given weaponID

防范无效 ID:

如果提供的weaponID 存在不存在的风险,您可以在尝试访问其成员之前先使用.ContainsKey() 方法检查它:

if (_WeapList.ContainsKey(weaponID))
{
    // Retrieve the weapon and access its members
}
else
{
    // Weapon doesn't exist, default behaviour
}

或者,如果您习惯使用 out 参数,您可以使用 .TryGetValue() 代替验证 - 这比单独调用 .ContainsKey() 更快:

data weaponData;
if (_WeapList.TryGetValue(weaponID, out weaponData))
{
    // weaponData is now populated with the weapon and you can access members on it
}
else
{
    // Weapon doesn't exist, default behaviour
}

希望这会有所帮助!如果您有任何问题,请告诉我。

【讨论】:

  • 如果ID不存在,你会得到异常吗?
  • @Programmer 是的 - 如果 OP 需要担心这一点,我将添加一条说明如何防止这种情况发生。
  • 好的。我这么说是因为 OP 听起来像是他的新人。我认为 TryGetValue 应该这样做。
  • @Programmer 啊,我也会提到一个 - 有点不确定使用 out 值是否会混淆 OP,但我想为了完整起见应该提到它。 .
  • 它可能但 OP 可以谷歌它。 @OP Dictionary 适合于此,因为数据库中会有很多数据。使用 linq 或 for 循环会比 Dictionary 慢很多。
【解决方案2】:

specificWeapon成为列表中要搜索的武器,然后您可以使用以下代码从武器列表中选择该项目,如果没有找到则返回null。希望这是您正在寻找的:

var selectedWeapon =  WeapList.FirstOrDefault(x=> x.ID == specificWeapon.ID);
if(selectedWeapon != null)
{
    // this is your weapon proceed
}
else
{
   // not found your weapon
}

【讨论】:

    【解决方案3】:

    您可以使用LINQ通过 WeaponId 搜索特定对象

    var Weapon =  _WeapList.FirstOrDefault(w=> w.ID == weaponId);
    

    【讨论】:

      猜你喜欢
      • 2021-11-15
      • 1970-01-01
      • 2019-12-21
      • 2022-11-02
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多