Brarord
Brarord

Reputation: 651

How to check if element is null before add it to list?

I have that code:

List<Move> list = new List<Move>();
list.Add(GetBeatingForFieldOnSpecificDiagonal(i, enemyColor, Constant.TOP_LEFT));
list.Add(GetBeatingForFieldOnSpecificDiagonal(i, enemyColor, Constant.TOP_RIGHT));
list.Add(GetBeatingForFieldOnSpecificDiagonal(i, enemyColor, Constant.DOWN_LEFT));
list.Add(GetBeatingForFieldOnSpecificDiagonal(i, enemyColor, Constant.DOWN_RIGHT));

The question is:
Is this possible to somehow check if this element is not null before add it to the list?
I mean I don't want to call that method twice. One call for check it is not null and another for eventually add it, this is a bad way, because I am writing an AI algorithm for computer and any resources are important.

Upvotes: 0

Views: 3314

Answers (3)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112334

Solution 1:

Use the Try... out var -pattern.

private bool TryGetHitForFieldOnDiagonal(int i, Color enemyColor, Constant constant,
                                         out Move move)
{
    // pesudo code
    if (finds_a_diagonal) {
        move = get_some_move;
        return true;
    }
    move = null;
    return false;
}

Then

if (TryGetHitForFieldOnDiagonal(i, enemyColor, Constant.TOP_LEFT, out var m)) list.Add(m);
if (TryGetHitForFieldOnDiagonal(i, enemyColor, Constant.TOP_RIGHT, out m)) list.Add(m);
if (TryGetHitForFieldOnDiagonal(i, enemyColor, Constant.DOWN_LEFT, out m)) list.Add(m);
if (TryGetHitForFieldOnDiagonal(i, enemyColor, Constant.DOWN_RIGHT, out m)) list.Add(m);

Solution 2:

Use C#8.0 pattern matching and loop over the constants:

foreach (Constant c in Enum.GetValues(typeof(Constant))) {
    if (GetHitForFieldOnDiagonal(i, enemyColor, c) is { } move) list.Add(move);
}

The pattern { } move is an empty property pattern. It tests whether the returned value is not null and binds the result to the new variable move.


Solution 3:

The loop of solution 2 assumes that you want to loop over all the constants. If you don't want to do this, you can instead use this pattern matching four times.

if (GetHitForFieldOnDiagonal(i, enemyColor, Constant.TOP_LEFT) is { } m1) list.Add(m1);
if (GetHitForFieldOnDiagonal(i, enemyColor, Constant.TOP_RIGHT) is { } m2) list.Add(m2);
if (GetHitForFieldOnDiagonal(i, enemyColor, Constant.DOWN_LEFT) is { } m3) list.Add(m3);
if (GetHitForFieldOnDiagonal(i, enemyColor, Constant.DOWN_RIGHT) is { } m4) list.Add(m4);

Solution 4:

In C#8.0, you can also declare local functions, i.e., methods embedded within other methods.

void AddNonNullHitToList(Constant constant) // local function
{
    if (GetHitForFieldOnDiagonal(i, enemyColor, constant) is { } m) list.Add(m);
}

AddNonNullHitToList(Constant.TOP_LEFT);
AddNonNullHitToList(Constant.TOP_RIGHT);
AddNonNullHitToList(Constant.DOWN_LEFT);
AddNonNullHitToList(Constant.DOWN_RIGHT);

Note that this local function has access to the variables of the surrounding method (here i, enemyColor and list).

Upvotes: 1

David
David

Reputation: 218837

The simplest approach is probably to just filter the list for non-null elements after adding them:

list = list.Where(l => l != null);

or possibly:

list = list.Where(l => l != null).ToList();

to materialize it to a List<> immediately, since list is explicitly a list type.

Upvotes: 3

Mureinik
Mureinik

Reputation: 311188

You can store the value into a variable, check if it's null, and then add it to the list:

Move tmp = GetBeatingForFieldOnSpecificDiagonal(i, enemyColor, Constant.TOP_LEFT);
if (tmp != null) {
    list.Add(tmp);
}
// The same can (should?) be done for the other moves

Upvotes: 1

Related Questions