这是错误的吗?为什么不是? 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 的每个元素。
这是我的代码示例,我在其中显示有关我的客户的信息:
<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 的每个元素。