【问题标题】:pass-by-Value,Pass-by-reference and changing value of object in Generic list VB通用列表VB中的按值传递,按引用传递和更改对象的值
【发布时间】:2016-08-29 06:33:43
【问题描述】:

嗨,我只是想在 vb 中使用 Byref 和 ByVal 做一些事情显然。下面是我试图更改 arr List 值的方法,但它给出了 Collection 已修改的异常;枚举操作可能无法执行,请帮忙理解Byval和Byref的这个逻辑。

   Public Function arrayReturn() As List(Of Object)
        Dim arr As List(Of Object)
        arr = New List(Of Object)
        For index As Integer = 1 To 5
            arr.Add(index)
            Debug.Write(index.ToString & " ")
        Next
        For Each i As Object In arr
            arr.Add(intReturn(i))
        Next
        Return arr
    End Function
    Public Function intReturn(ByRef i As Object) As Integer
        i += i
        Return i
    End Function
    Sub Main()
        Dim obj As List(Of Object)
        obj = New List(Of Object)
        obj = arrayReturn()
        For Each obj2 As Object In obj
            Console.WriteLine(obj2)
        Next
    End Sub

我的问题是这个方法在这里我试图检索一个事件对象并将其放入事件列表中,但我不知道我是否正确

Public Function GetIcalForAppointments(nxtMonth As Integer, prevMonth As Integer, strStaffAPIKey As String) As Ical.NET.Calendar
        Dim objDTOIcallApt As DTOICallAppt
        objDTOIcallApt = New DTOICallAppt
        Dim lst As List(Of DOAppointment)

        objDTOIcallApt = GetAllAppointmentsForIcal(nxtMonth, prevMonth, strStaffAPIKey)
        lst = objDTOIcallApt.Appointments
        Dim timeZoneName As String = objDTOIcallApt.UserTimezone
        Dim calendar As Ical.NET.Calendar
        calendar = New Ical.NET.Calendar()
        Dim timeZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName)
        calendar.AddTimeZone(New Ical.NET.VTimeZone(timeZoneName))
        Dim evt As Ical.NET.Event
        For Each appt As DOAppointment In lst
            GetIcalForAppointment(appt, objDTOIcallApt, calendar, evt)
        Next
        Return calendar

    End Function


Public Function GetIcalForAppointment(app As DOAppointment, objResponse As DTOICallAppt, calendar As Ical.NET.Calendar, ByRef evt As Ical.NET.Event) As Ical.NET.Event

        evt = calendar.Create(Of Ical.NET.Event)()
        evt.Start = getCalDateTime(app.StartDate, calendar)
        evt.End = getCalDateTime(app.EndDate, calendar)
        evt.Description = app.FullSubject
        evt.Location = app.AppointmentInOrgName
        evt.IsAllDay = False
        evt.Created = getCalDateTime(app.CreatedDatetime, calendar)
        If objResponse.UserEmail <> "" AndAlso objResponse.UserEmail.Contains("@") = True Then
            evt.Organizer = New Organizer("MAILTO:" + objResponse.UserEmail)
        End If

        Select Case app.AppointmentStatus
            Case "Cancelled"
                evt.Status = Ical.NET.EventStatus.Cancelled
                Exit Select
            Case "NoShow"
                evt.Status = Ical.NET.EventStatus.Cancelled
                Exit Select
            Case "Scheduled"
                evt.Status = Ical.NET.EventStatus.Tentative
                Exit Select
            Case Else

                evt.Status = Ical.NET.EventStatus.Confirmed
                Exit Select
        End Select

        evt.Categories.Add("Work")
        evt.Comments.Add(app.CreatedDetails)
        evt.Resources.Add(app.Resource1Name)
        evt.Resources.Add(app.Resource2Name)
        Dim strSummary As String = app.FullSubject
        If app.IsPatConsentRequired = True Then
            If app.IsPatConsentGiven = True Then
                strSummary = strSummary & Convert.ToString(" | Consent given")
            Else
                strSummary = strSummary & Convert.ToString(" | Consent Pending")
            End If
        End If

        If app.PatMedicalHistoryCasesheetID <> "" Then
            If app.IsMedicalHistoryFilled = True Then
                strSummary = strSummary & Convert.ToString(" | Medical History filled")
            Else
                strSummary = strSummary & Convert.ToString(" | Medical History pending")
            End If
        End If

        evt.Summary = strSummary
        evt.Uid = app.ID
        Dim alarm As New Ical.NET.Alarm
        alarm.Action = Ical.NET.AlarmAction.Display
        alarm.Summary = "Appointment with " + app.AppointmentWithFullName + " at " + app.AppointmentInOrgName
        alarm.Trigger = New Trigger(TimeSpan.FromMinutes(-30))
        evt.Alarms.Add(alarm)
        Return evt

    End Function

所以在这里你可以看到我每次都在检索单个事件对象并尝试将其推送到事件列表中

【问题讨论】:

  • 在您的第二个 for 循环中,您将添加新元素而不是更改现有元素。 arr(i) = intReturn(i) 应该可以工作。
  • 以及如何处理在其他方法中填充的对象,但对于 foreach 循环...@turamarth
  • 如果唯一的问题是异常,@Turamarth 是对的。如果您需要更多帮助,您需要重写您的答案以说明具体问题或为每个问题编写多个问题。如果您需要解释什么是 byref 和 byval 的手册,here 它是

标签: asp.net vb.net pass-by-reference pass-by-value


【解决方案1】:

首先,我认为 ByVal 和 ByRef 与您的问题无关。阅读更多关于他们的信息here 我相信您的问题与您使用的逻辑有关。 让我们分解您的 arrayReturn 函数,看看发生了什么:

   Public Function arrayReturn() As List(Of Object)
    Dim arr As List(Of Object)
    arr = New List(Of Object)

您正在声明和实例化一个通用对象列表,这很好。顺便说一句,您可以将这段代码缩短为一行 Dim arr as new List(Of Object)。

    For index As Integer = 1 To 5
        arr.Add(index)
        Debug.Write(index.ToString & " ")
    Next

您在列表中添加了 5 个对象,这里没有错。

    For Each i As Object In arr

这里是重点。这个声明实际上是你和VB之间的契约,你在这里说的是“对于列表中的5个对象中的每一个都做某事”。也就是说,您是在指示 VB 对列表中的 5 个对象中的每一个执行某些操作,或者更具体地说,在这个非常特定的时间点对列表中当前对象总数中的每个对象执行某些操作。

VB 内部所做的是准备环境以迭代列表中的所有对象,在本例中为 5。

        arr.Add(intReturn(i))

这是您违反合同的地方。您正在列表中添加另一个对象,因此不再有 5 个对象,并且迭代无法继续,因为 VB 为 5 个对象而不是 6 个对象准备了一切。

这是正确的行为,您在迭代列表周期时不能更改对象的计数。但是让我们说,为了这个例子的震动,你能够做到这一点。在这种情况下,您的循环将永远不会完成,因为您是在告诉 VB 对列表中的每个对象以及每次添加项目时执行一个操作。如果要考虑该项目,那么“每个”将变得无限,因此循环将是无限的。我希望你明白这一点

    Next
    Return arr
End Function

我从您的代码中了解到,您希望在列表中添加与当前存在的对象相同数量的对象,在本例中为 5。如果这是真的,那么您必须按如下方式修改您的函数:

Public Function arrayReturn() As List(Of Object)
    Dim arr As New List(Of Object)

    For index As Integer = 1 To 5
        arr.Add(index)
        Debug.Write(index.ToString & " ")
    Next

    Dim c as Integer = arr.Count

    For i As Integer = 0 to c - 1
        arr.Add(intReturn(arr(i)))
    Next

    Return arr
End Function

但是,这对于约会应用范围来说并不正确。例如,如果其他约会中有子约会,那么您需要一个不同的存储结构(如树)并递归访问/操作它。

希望这会有所帮助。

【讨论】:

  • 感谢您的回复,但该代码只是一个虚拟代码,我试图传递一些对象并将其返回到列表中,实际上我正在尝试在下一个代码中为每个 appt对象试图创建事件,最后我会得到一个事件列表,但为此我需要将对象作为参考传递,以便在事件列表中第一个对象是一个事件,然后是下一个事件,然后是下一个
猜你喜欢
  • 1970-01-01
  • 2014-08-23
  • 2015-05-23
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
  • 2014-04-04
  • 1970-01-01
相关资源
最近更新 更多