.net 传递列表';函数的枚举数

.net 传递列表';函数的枚举数,.net,vb.net,enumerator,.net,Vb.net,Enumerator,看起来,将列表的枚举数传递给函数“byval”与将其传递给函数“byref”完全不同。从本质上讲,常规的“byval”传递不会更改调用方的“enumerator.Current value”,即使函数使枚举数前进。我想知道是否有人知道为什么会这样?枚举数是一个类似于整数的基元,没有对象引用,因此对它的更改不会反映在调用方中吗 以下是示例代码: 此函数为byval,陷入无限循环,弹出“1”消息框,因为枚举数的“current”永远不会超过5: Public Sub listItemsUsingBy

看起来,将列表的枚举数传递给函数“byval”与将其传递给函数“byref”完全不同。从本质上讲,常规的“byval”传递不会更改调用方的“enumerator.Current value”,即使函数使枚举数前进。我想知道是否有人知道为什么会这样?枚举数是一个类似于整数的基元,没有对象引用,因此对它的更改不会反映在调用方中吗

以下是示例代码:

此函数为byval,陷入无限循环,弹出“1”消息框,因为枚举数的“current”永远不会超过5:

Public Sub listItemsUsingByValFunction()
    Dim list As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

    Dim enumerator = list.GetEnumerator()
    enumerator.MoveNext()
    While enumerator.Current <= 5
        listFirstItemByVal(enumerator)
    End While
End Sub
Private Sub listFirstItemByVal(ByVal enumerator As List(Of Integer).Enumerator)
    MsgBox(enumerator.Current)
    enumerator.MoveNext()
End Sub
使用ByValFunction()的公共子列表项 作为(整数的)新列表的Dim列表(新整数(){1,2,3,4,5,6,7,8,9,10}) Dim枚举器=list.GetEnumerator() 枚举数。MoveNext()
While enumerator.Current您看到这种行为的原因是
List(Of T)。enumerator
是一个
Struct
,而不是通常预期的
类。因此,当您传递枚举数时,您传递了它的一个副本,因此当您调用
MoveNext

时,使用所提供的示例代码将不会使用选项Strict On编译该副本。修正这一点可能会修正你所看到的差异

Public Sub listItemsUsingByValFunction()
    Dim list As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

    Dim enumerator As IEnumerator(Of Integer) = list.GetEnumerator()
    enumerator.MoveNext()
    Debug.WriteLine("S " & enumerator.Current)
    Stop
    Do
        Debug.WriteLine("W " & enumerator.Current)
        If Not listFirstItemByVal(enumerator) Then Exit Do
    Loop
End Sub

Private Function listFirstItemByVal(ByVal enumerator As IEnumerator(Of Integer)) As Boolean
    Debug.WriteLine("F " & enumerator.Current)
    Return enumerator.MoveNext()
End Function

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    listItemsUsingByValFunction()
End Sub

有趣!谢谢你澄清这一点!所以,如果您将枚举数传递给函数,您是否总是在心里记下使用“byref”?例如,是否有一些解决方法可以避免总是记住这一点,特别是因为Visual Studio将自动生成总是使用byval的方法,因此这样的事情可能很容易被忽略?@MichaelZlatkovsky如果使用
IEnumerator(Of T)
,则无需这样做,这是最常见的情况。每当我传递特定于类型的枚举数时,我总是在执行
ByVal
vs.
ByRef
之前检查类型,真的吗?我在原始代码中添加了“Option Strict On”,但仍然没有收到任何警告或错误。我应该说,Option Strict On,Option Inferre Off,Option Explicit On。抱歉。嗯,我没有意识到关闭推断功能会捕获未显示的错误(当我第一次设置项目时,我有点假设“打开”的东西越多越好!)在你看来,关闭推断功能是一种最佳实践吗?它不需要更多的输入吗?例如,它值得你这么做吗?我喜欢Option Strict On,Option Inferre Off,Option Explicit On。它更多的是打字,但它有助于捕捉像这样的错误。当你第一次花上几个小时去寻找一个错误,而这个错误是由一些你认为不是的东西引起的,这会让你信服。这很公平。顺便问一下,C#呢?您知道它是否有类似的“选项推断”开关吗?我已经看到越来越多的代码似乎确实使用了推断,但我不确定C#编译器是否有更好的“感觉”来推断什么是安全的,什么是不安全的。。。
Public Sub listItemsUsingByValFunction()
    Dim list As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

    Dim enumerator As IEnumerator(Of Integer) = list.GetEnumerator()
    enumerator.MoveNext()
    Debug.WriteLine("S " & enumerator.Current)
    Stop
    Do
        Debug.WriteLine("W " & enumerator.Current)
        If Not listFirstItemByVal(enumerator) Then Exit Do
    Loop
End Sub

Private Function listFirstItemByVal(ByVal enumerator As IEnumerator(Of Integer)) As Boolean
    Debug.WriteLine("F " & enumerator.Current)
    Return enumerator.MoveNext()
End Function

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    listItemsUsingByValFunction()
End Sub