如何在将元素添加到列表之前检查元素是否为空?

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

我有那个代码:

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));

问题是:
是否可以在将此元素添加到列表之前以某种方式检查它是否不为空?
我的意思是我不想调用那个方法两次。一个要求检查它不为空,另一个要求最终添加它,这是一种糟糕的方式,因为我正在为计算机编写 AI 算法,任何资源都很重要。

最简单的方法可能是在添加非空元素后过滤列表:

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

或者可能:

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

立即将其具体化为 List<>,因为 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

解决方案一:

使用 Try...out var 模式。

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;
}

然后

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);

方案二:

使用 C#8.0 模式匹配并遍历常量:

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

模式 { } move 是空 属性 模式。它测试返回值是否不为 null 并将结果绑定到新变量 move.


方案三:

解决方案2的循环假定您要遍历所有常量。如果你不想这样做,你可以使用这个模式匹配四次。

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);

方案四:

在 C#8.0 中,您还可以声明局部函数,即嵌入在其他方法中的方法。

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);

请注意,此局部函数可以访问周围方法的变量(此处为 ienemyColorlist)。