【问题标题】:vb.net Passing a list through a function without list value changed [duplicate]vb.net通过没有更改列表值的函数传递列表[重复]
【发布时间】:2018-08-08 02:22:44
【问题描述】:

这里的list值在传递ByVal时改变了为什么 ,不能更改。

Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
        Dim value As Integer = 1
        Dim value2 As New List(Of Decimal)
        value2.Add(1)
        value2.Add(2)

        ' The integer value doesn't change here when passed ByVal.
        Example1(value)
        Console.WriteLine(value)

        ' The list value changeed here when passed ByVal.
        Example3(value2)
        Console.WriteLine(value)

结束子

    Sub Example1(ByVal test As Integer)
        test = 10
    End Sub

    Sub Example3(ByVal test As List(Of Decimal))
        test.Add(3)
    End Sub

解决了,解决方法是制作新副本:

Sub Example3(ByVal test As List(Of Decimal))
        Dim testnew As New List(Of Decimal)
        testnew.AddRange(test)
        testnew.Add(3)
    End Sub

【问题讨论】:

    标签: vb.net list function arguments


    【解决方案1】:

    您需要阅读值类型和引用类型以及按值和按引用传递方法参数。它们是相关的,但不是一回事。当您按值传递方法参数时,您会创建正在传递的变量的副本。如果变量是值类型,即结构,则意味着创建值的副本。如果变量是引用类型,即类,那么这意味着创建引用的副本。问题是,原始引用和副本仍然引用同一个对象。

    存在引用类型的原因是您不希望每次将大型对象分配到某个位置时都创建它们的副本。在将集合传递给方法的情况下,几乎总是这样,您在方法内部所做的任何更改都希望在外部反映出来。在极少数情况下,您可以先创建集合的副本并将其传入。

    当您按值传递值类型时,您会创建该值的副本。这意味着您在方法内部所做的任何更改都不会影响原始变量。您可以为参数分配一个新值,也可以设置该值的属性,并且更改不会反映在方法之外。当然,值类型通常应该是不可变的,因此无法设置属性,但有时该“规则”会被打破。

    当您按值传递引用类型时,您会创建引用的副本。这意味着为方法内部的参数分配不同的对象不会影响原始变量。但是仍然只有一个对象,由原始变量和参数引用。因此,如果您通过参数设置该对象的属性,那么该更改将反映在原始变量中,因为它是同一个对象。

    当您通过引用传递值类型时,您会创建对该值的新引用。这意味着您在方法内所做的任何更改都会影响原始变量。您可以为参数分配一个新值,也可以设置该值的属性,并且更改将反映在方法之外。

    当您通过引用传递引用类型时,您将创建一个对原始引用的新引用。这意味着将不同的对象分配给方法内部的参数将影响原始变量。仍然只有一个对象,因此在参数上设置属性仍然会影响原始变量。

    只有这四种可能性:值类型、值类型、值类型、引用类型和引用类型。在这些场景中,都不是引用类型对象的副本,因此在这些场景中,您都不能通过方法参数设置引用类型对象的属性,并且该更改不会反映在原始变量中。

    如果您想要原始对象的副本,则由您明确创建一个。是在方法内部还是外部这样做,实际上取决于具体情况。这意味着您需要将代码更改为:

    Sub Example3(ByVal test As List(Of Decimal))
        Dim copy = test.ToList()
    
        copy.Add(3)
    End Sub
    

    或者这个:

    Dim copy = value2.ToList()
    
    Example3(copy)
    

    让我在这里重复重点:没有办法将引用类型对象传递给方法,通过方法内部的参数修改对象并且不影响原始变量(将不同的对象分配给参数不修改对象)。如果您希望方法内部的修改不影响原始变量,那么您需要一个对象的副本,并且唯一的方法是您明确地这样做。

    【讨论】:

    • 谢谢你的回答,我知道这一切,但如果参数是 list(of...) 它的值改变了,我使用它 byref 或 byvalue
    • 如果你还在问这个问题,我不确定你是否知道这一切。我会在我的答案中添加更多信息。
    • 你应该看看更新的答案。
    • 感谢您的回答,通过复制解决了
    猜你喜欢
    • 2016-06-09
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    相关资源
    最近更新 更多