3

I'm creating a game in Unity3D + C#.

What I've got at the moment: an SQL datatable, consisting of 8 columns holding a total of 3 entries and a list "_WeapList" that holds every entry (as shown below).

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
    }

Now I want to create a "Weapon"-Class that will have the same 8 fields, feeding them via a given ID

How do I extract the values of a specific item (determined by the int ID, which is always unique) in the list/struct?

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...?
    }
}
sujith karivelil
  • 28,671
  • 6
  • 55
  • 88
Csharpest
  • 1,258
  • 14
  • 32
  • If you're going to be doing these lookups often, why not use a Dictionary instead of a List? Something like `Dictionary _WeapList`, with the index being the ID of the weapon. Then you can just access it with `_WeapList[weaponID]`, and it'll be a lot quicker than using a loop/LINQ to search through a List. – Serlite Jan 05 '17 at 17:05
  • You probably want to rethink using a mutable struct. I'd suggest either making it a class (with properties instead of public fields) or make the struct immutable by adding a constructor that sets private fields and exposes read only properties. http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil – juharr Jan 05 '17 at 17:15
  • First of all: thank you, I've never used LINQ expressions before, despite that I will also rethink about the struct issue. Nevertheless I do not unterstand how to feed the dictionary, neither do I know how to find for example int dmg of weapon with ID "3". I've created a dictionary and put this "_WeapoList.Add(itm.ID, itm);" into the while(rdr.Read()){ ... }. How would I parse the "dmg" value to my weapon class? dmg = database._WeapList[ ??? ] (I've put these changes into the code above) – Csharpest Jan 05 '17 at 17:29
  • @Csharpest You get back a `data` object from `_WeapList[weaponID]`. So to access any members of it, just use the `.` syntax, eg. `_WeapList[weaponID].dmg`. – Serlite Jan 05 '17 at 17:31
  • @Serlite Why not put answer for that? – Programmer Jan 05 '17 at 17:32
  • 1
    @Programmer I wanted to first ascertain that the OP wasn't opposed to using a Dictionary for some reason - since it sounds like he's considering it, I think I will put it as answer shortly. – Serlite Jan 05 '17 at 17:33

3 Answers3

4

If your collection of weapons may become quite large or you need to frequently look up weapons in it, I would suggest using a Dictionary instead of a List for this (using the weapon ID as the key). A lookup will be much quicker using a Dictionary key than searching through a List using a loop or LINQ.

You can do this by modifying your code to do this as follows:

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
}

Then, to access elements on the list, just use the syntax:

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

Guarding against invalid IDs:

If there's a risk of the weaponID supplied not existing, you can use the .ContainsKey() method to check for it first before trying to access its members:

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

Alternatively, if you're comfortable using out arguments, you can use .TryGetValue() instead for validation - this is even quicker than calling .ContainsKey() separately:

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
}

Hope this helps! Let me know if you have any questions.

Community
  • 1
  • 1
Serlite
  • 12,130
  • 5
  • 38
  • 49
  • Do you get exception if the ID does not exist? – Programmer Jan 05 '17 at 17:38
  • 1
    @Programmer Yeah - I'll add a note on how to guard against that, if the OP needs to worry about that. – Serlite Jan 05 '17 at 17:40
  • 1
    Ok. I said that because OP sounds like he's new. I think TryGetValue should do it. – Programmer Jan 05 '17 at 17:41
  • 2
    @Programmer Ah, I'll mention that one as well - was a little uncertain whether using an `out` value might confuse the OP, but I suppose it should be mentioned for completeness' sake... – Serlite Jan 05 '17 at 17:44
  • 1
    It might but OP can google it. @OP Dictionary is appropriate for this since there will be many data from the database. Using linq or for loop will be a-lot slower than Dictionary. – Programmer Jan 05 '17 at 17:53
  • Wonderful! This completely sealed the deal! I'm really thankful, it works flawlessly so far! I'm also thankful for the ".TryGetValue" advice, I'll include it, too. – Csharpest Jan 05 '17 at 17:59
2

Let specificWeapon be a weapon to be searched in the list, then you can use the following code to select that item from the list of weapons, if it is not found then nullwill be returned. Hope that this what you are looking for:

var selectedWeapon =  WeapList.FirstOrDefault(x=> x.ID == specificWeapon.ID);
if(selectedWeapon != null)
{
    // this is your weapon proceed
}
else
{
   // not found your weapon
}
sujith karivelil
  • 28,671
  • 6
  • 55
  • 88
1

You can use LINQ to search specific object through weaponId

var Weapon =  _WeapList.FirstOrDefault(w=> w.ID == weaponId);
Ahmar
  • 3,717
  • 2
  • 24
  • 42