这是错误的吗?为什么不是? ASP.NET MVC 视图包

Is this wrong and why it's not ? ASP.NET MVC ViewBag

这是我的代码示例,我在其中显示有关我的客户的信息:

<table class="table table-striped  jambo_table bulk_action">
   <thead>
      <tr class="headings">
         <th class="column-title">Address </th>
         <th class="column-title">Title</th>                                            
      </tr>
   </thead>
   <tbody>
    @foreach (var customer in ViewBag.Customers)
    {
     <tr>
      <td>@customer.Code</td>
      <td>@customer.DefaultName.Name</td>
     </tr>
    }
   </tbody>
</table>

正如你们所看到的,我正在循环 ViewBag 以在我的 table 中显示一些数据, 然后我在ViewBag.Customer里面没有数据的时候测试了一下,也没有抛出任何异常, 为什么 foreach 没有在空列表上抛出异常?

我以为我会得到类似的东西:

Object reference not set to an instance of an object

如果我在 ViewBag.Customer 中没有数据时尝试循环..

怎么会?

Foreach循环调用GetEnumerator方法。如果它是空枚举器,它不会抛出错误(即:它只是退出循环)。

如果集合为 null,此方法调用将导致 NullReferenceException,因为它无法获取枚举数。在这种情况下,您的控制器必须返回一个空列表才能不抛出错误。

正如@hsoesanto 所说,IEnumerable 调用 GetEnumerator,它 returns 是 IEnumerator 的一个实例,但如果集合为空,它不会抛出任何异常。

这是ICollection的原始代码

[__DynamicallyInvokable]
public IEnumerator<T> GetEnumerator()
{
  return this.items.GetEnumerator();
}

但是如果你深入了解,让我们说一个实现 ICollection 的列表的实现,当它 returns 列表的枚举器时,你会看到对列表大小的检查

[__DynamicallyInvokable]
[Serializable]
public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator
{
   ....

  [__DynamicallyInvokable]
  public bool MoveNext()
  {
    List<T> list = this.list;
    if (this.version != list._version || (uint) this.index >= (uint) list._size)
      return this.MoveNextRare();
    this.current = list._items[this.index];
    this.index = this.index + 1;
    return true;
  }

正如你在这一行看到的那样

if (this.version != list._version || (uint) this.index >= (uint) list._size)

这意味着当您尝试遍历空元素集合时,MoveNext returns false 然后 foreach 结束。

因此回到您的 ViewBag,如​​果 Customers 不为空,您不应收到任何错误或异常,首先编译器会在 运行 时检测到您正在 ViewBag 上使用元素集合,如果它不为 null,则它对其进行迭代,在 returns IEnumerator 的那个集合上调用 GetEnumerator,并调用 MoveNext 和 Current 来获取 List 的每个元素。