Search code examples
c#listnullfind

Using Exists with a Predicate<T> on a list with null items


I'm trying to find the index of an item in a list with something like

listx.FindIndex(SomePredicate<T>) 

but I get an error

NullReferenceException: Object reference not set to an instance of an object

At first I was not exactly sure what it was so I also tried using something like listx.Exists(SomePredicate<T>). The list has a fixed length and does contain null values (it's for building an inventory system in Unity).

My (very) simplified code:

public class Item
{
    public int id;
    public string itemname;

    // constructor etc ...
}

// in another class:

    List<Item> inventory = new List<Item>();

    for (int i = 0; i < 4; i++)
    {
        inventory.Add(null);
    }

    inventory[0] = new Item(0, "YellowBox");
    inventory[1] = new Item(1, "RedBox");
    // inventory[2] stays null
    // inventory[3] stays null

    string itemname = "RedBox";
    inventory.Exists(item => item.itemname == itemname)
    // WORKING because it finds a match before it runs into a null

    string itemname = "BlueBox";
    inventory.Exists(item => item.itemname == itemname)
    // NOT WORKING, I guess because it runs into a null in inventory[2]
    // and it can't get an itemname from null

Does anybody know to check for null first or has an alternative for .Exists?

Writing this question I now got an idea. Just skipping null doesn't suffice I think because I need the index but maybe something like this.

public int FindItemIndex(string itemname)
{
    int index = -1;

    for (int i = 0; i < 4; i++)
    {
        if (inventory[i] == null) 
        { 
            continue; 
        }

        if (inventory[i].itemname == itemname) 
        {
             return i;
        }
    }

    return index;
}

Then I could use something like:

if (FindItemIndex(string itemname) < 0) 
{ 
    // code for item not found 
}
else 
{ 
    // code where I use the index, for example remove item at inventory[index]
}

Or is inventory.Where(Item => Item != null) usable?

I'd appreciate some suggestions


Solution

  • inventory.Exists(item => item?.itemname == itemName)
    

    item?.itemname means if item is not null then call itemname. If the item is null, the predicate resolves to null == itemName

    Linqs .Any also works ie.

    var inventoryItemExists = inventory.Any(item => item?.itemName == itemName);
    

    You can use where ie.

    var inventoryItemExists = inventory.Where(item => item != null).Any(item => item.itemName == itemName);