检查数组是否为空或者为null?

9
我对这行代码有些问题:
if(String.IsNullOrEmpty(m_nameList[index]))

我做错了什么?

编辑:在VisualStudio中,m_nameList被红色下划线标出,并显示“当前上下文中不存在名称'm_nameList'”?

编辑2:我添加了一些代码。

    class SeatManager
{
    // Fields
    private readonly int m_totNumOfSeats;

    // Constructor
    public SeatManager(int maxNumOfSeats)
    {
        m_totNumOfSeats = maxNumOfSeats;

        // Create arrays for name and price
        string[] m_nameList = new string[m_totNumOfSeats];
        double[] m_priceList = new double[m_totNumOfSeats];
    }

    public int GetNumReserved()
    {
        int totalAmountReserved = 0;

        for (int index = 0; index <= m_totNumOfSeats; index++)
        {
            if (String.IsNullOrEmpty(m_nameList[index]))
            {
                totalAmountReserved++;
            }
        }
        return totalAmountReserved;
    }
  }
}

2
什么样的问题?你遇到了IndexOutOfRangeException吗? 请发布您的错误。 - cichy
那就对了,马龙...我撤回我的评论。 - Yavar
3个回答

18

如果 m_nameList 是空的,那么它仍然会崩溃,因为它将尝试找到要传递给 String.IsNullOrEmpty 的元素。你需要这样写:

if (m_nameList == null || String.IsNullOrEmpty(m_nameList[index]))

这也假设如果m_nameList非空,则index将是有效的。

当然,这是在检查一个数组元素是否为null或为空,或者数组引用本身是否为null。如果你只想检查数组本身(如您的标题所示),则应该使用:

if (m_nameList == null || m_nameList.Length == 0)

编辑:现在我们可以看到您的代码,有两个问题:

  • 正如Henk在他的答案中所示,您正在尝试使用一个局部变量,而您需要一个字段。
  • 一旦您使用了一个字段,您也会因为这个原因得到一个ArrayIndexOutOfBoundsException

for (int index = 0; index <= m_totNumOfSeats; index++)

由于您的绑定,这将执行m_totNumOfSeats + 1次迭代。您需要:

for (int index = 0; index < m_totNumOfSeats; index++)
请注意,m_nameList[m_totNumOfSeats] 不是有效的,因为在 C# 中数组索引从 0 开始。因此,对于一个包含 5 个元素的数组,有效的索引是 0、1、2、3、4。

你的 GetNumReserved 方法的另一个选项是使用:

int count = 0;
foreach (string name in m_nameList)
{
    if (string.IsNullOrEmpty(name))
    {
        count++;
    }
}
return count;

或者使用 LINQ,这可以写成一行:

return m_nameList.Count(string.IsNullOrEmpty);

你确定你没有弄反吗?我认为预订应该是那些名称不是 null 或空的,而不是那些 null 或空的。

如果是相反的情况,在LINQ中应该是这样:

return m_nameList.Count(name => !string.IsNullOrEmpty(name));

@Downvoter:可以发表一下评论吗?请记住,这个答案是在问题发布代码之前写的... - Jon Skeet
1
谢谢帮助!是的,代码现在是反过来的!我会修复它! - 3D-kreativ

6

编辑后:

你把 m_nameList 定义为构造函数的局部变量。
你的其余代码需要它作为一个字段:

class SeatManager
{       
   // Fields
   private readonly int m_totNumOfSeats;
   private string[] m_nameList;
   private double[] m_priceList;

  // Constructor
  public SeatManager(int maxNumOfSeats)
  {
     m_totNumOfSeats = maxNumOfSeats;

     // Create arrays for name and price
     m_nameList = new string[m_totNumOfSeats];
     m_priceList = new double[m_totNumOfSeats];
  }

  ....
}

太好了!我错过了那个!感谢你的帮助! :) - 3D-kreativ
@3D-kreativ:请注意,那只是代码中的一个问题 - 另请查看我的答案。 - Jon Skeet

4
为了避免错误,你可以在if语句中执行一些预先条件,例如:

要避免错误,可以在if语句中执行一些预处理条件,例如:

if(m_nameList == null || index < 0 || m_nameList.Length < index || String.IsNullOrEmpty(m_nameList[index]))

这个应该在几乎所有情况下都能正常工作(不会引起错误)...


不错。有很多测试在那里...我数了七个?不,是八个!这让我觉得异常确实是非常棒的! - Kevin P. Rice
1
@KevinP.Rice:我绝不会让异常直接通过并在此处捕获。ArrayIndexOutOfBounds异常应始终表示错误,而不是故意的。当然,我计算了四个测试(所有条件都使用OR运算符连接),而不是八个。这里检查了4个条件,所有条件都是有效的。您是否将每个复合条件都计算为额外的一个? - Jon Skeet
2
@KevinP.Rice:我认为任何不试图在此处达到最大可能数量的人都会将其视为四个条件。考虑到问题的标题是“检查数组是否为空或空?”,可以合理地假设OP确实想要执行检查。当然,让异常冒泡可能没问题,但这不是你建议的。你建议捕获异常:“如果很少见,则try/catch更好”。我绝对不同意。捕获ArrayIndexOutOfBoundsException或NullReferenceException只是一个坏主意。 - Jon Skeet
@JonSkeet 我从小就开始写机器码,所以我总是考虑“看似简单”的代码(特别是LINQ!)实际上生成了什么。你关于try/catch的观点是正确的;我不确定昨晚晚些时候我想表达什么!同意bubble-up,但是在包装容易失败的操作(例如HttpRequest)时,局部的try/catch偶尔也是有用的。能否请您对这个无关的问题发表一下评论?https://dev59.com/UWLVa4cB1Zd3GeqPvloW - Kevin P. Rice
1
@KevinP.Rice:今晚不行,但我会提醒自己明天查看。 - Jon Skeet
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接