gpt4 book ai didi

.net - List(Of T) 被未知英雄救了?

转载 作者:行者123 更新时间:2023-12-04 17:18:59 24 4
gpt4 key购买 nike

What prevents a List(Of T) from throwing an arithmetic overflow exception when I set the internal _version field to Integer.MaxValue and add a new item?



TL;博士:

正如您在查看源代码时看到的那样,没有针对潜在算术溢出的保护措施。但是有人/某事将值设置为 Integer.MinValue如果该值是最大值。
<__DynamicallyInvokable()> _
Public Sub Add(ByVal item As T)
If (Me._size = Me._items.Length) Then
Me.EnsureCapacity((Me._size + 1))
End If
Me._items(Me._size++) = item
Me._version += 1
End Sub

详细的

作为 List(Of T) 的内部项数组是私有(private)的,我不会使用反射来访问它,我决定使用原始的 List(Of T) 创建一个自定义列表源代码。

但是,我注意到如果版本达到 Integer.MaxValue,则无法防止潜在的算术溢出。 .
Me._version += 1

所以我修改了代码:
Me._version = If((Me._version = Integer.MaxValue), Integer.MinValue, (Me._version + 1I))

现在开始有趣的部分;出于好奇,我设置了一个测试,使用反射设置内部 _version场最大。
Dim flags As BindingFlags = (BindingFlags.Instance Or BindingFlags.NonPublic)
Dim list As New List(Of String)
Dim _version As FieldInfo = GetType(List(Of String)).GetField("_version", flags)

_version.SetValue(list, Integer.MaxValue)
Debug.WriteLine("Count: {0}, Version: {1}", list.Count, _version.GetValue(list))
list.Add("str")
Debug.WriteLine("Count: {0}, Version: {1}", list.Count, _version.GetValue(list))

我对结果感到震惊:

Count: 0, Version: 2147483647
Count: 1, Version: -2147483648



如果达到最大值,源代码中没有任何内容将字段设置为最小值。我什至看了 DynamicallyInvokable属性,但据我所知,它不相关。
<__DynamicallyInvokable()> _
Public Sub Add(ByVal item As T)
If (Me._size = Me._items.Length) Then
Me.EnsureCapacity((Me._size + 1))
End If
Me._items(Me._size++) = item
Me._version += 1
End Sub

Private Sub EnsureCapacity(ByVal min As Integer)
If (Me._items.Length < min) Then
Dim num As Integer = IIf((Me._items.Length = 0), 4, (Me._items.Length * 2))
If (num > &H7FEFFFFF) Then
num = &H7FEFFFFF
End If
If (num < min) Then
num = min
End If
Me.Capacity = num
End If
End Sub

<__DynamicallyInvokable()> _
Public Property Capacity As Integer
<TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable()> _
Get
Return Me._items.Length
End Get
<__DynamicallyInvokable()> _
Set(ByVal value As Integer)
If (value < Me._size) Then
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity)
End If
If (value <> Me._items.Length) Then
If (value > 0) Then
Dim destinationArray As T() = New T(value - 1) {}
If (Me._size > 0) Then
Array.Copy(Me._items, 0, destinationArray, 0, Me._size)
End If
Me._items = destinationArray
Else
Me._items = List(Of T)._emptyArray
End If
End If
End Set
End Property

最佳答案

基类库是用 C# 编写的,而不是 VB.NET。

默认情况下,C# 中的算术运算不会引发溢出异常。相反,正如您所注意到的,它们默默地将值包裹起来。

这个决定可能是出于效率的原因;不是每个人都同意它。更多信息可以在以下问题中找到:

  • Why doesn't C# use arithmetic overflow checking by default?
  • Why don't languages raise errors on integer overflow by default?
  • 关于.net - List(Of T) 被未知英雄救了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25740503/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com