将类对象添加到通用列表时,数据会被覆盖

时间:2013-02-26 18:49:29

标签: asp.net vb.net

我正在尝试将类对象(我认为这就是所谓的)添加到我的类的通用列表中。在下面的代码中,每当我更改TempQuoteReturnFromExecuteEstimate中的值时,它都会更改通用列表的所有行中的值。我猜它只是引用了这个对象。如何将值复制到通用列表?感谢

Dim AllEstimatesReturn As New List(Of QuoteReturnData)
Dim TempQuoteReturnFromExecuteEstimate As New QuoteReturnData
...
AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate)

3 个答案:

答案 0 :(得分:2)

你的假设是正确的。当您创建类类型(引用类型)变量时,它只是引用一个对象。您可以让许多不同的变量同时引用同一个对象。

在这种情况下,AllEstimatesReturn列表中的每个项目都是一个单独的QuoteReturnData变量。每个项目仅仅是对象的引用,而不是副本。因此,理论上,列表中的每个项都可以引用同一个对象,但通常这不是您想要的。

如果要为列表中的每个项目创建单独的对象,则每次都需要使用New关键字创建它们:

'Add the first item
Dim TempQuoteReturnFromExecuteEstimate As New QuoteReturnData
...
AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate)

'Add the second item
TempQuoteReturnFromExecuteEstimate = New QuoteReturnData  ' Use New to create another object
...
AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate)

请注意,在上面的示例中,我重用了相同的变量,只是更改了它的值,以便它引用一个新对象。旧对象仍然存在,因为它由列表对象引用。或者,您可以每次声明一个新变量,但是,除非您为了清晰起见而这样做,否则没有技术原因需要这样做。

答案 1 :(得分:1)

类类型是引用类型。因此,这会将相同对象的3个引用添加到列表中:

Dim AllEstimatesReturn As New List(Of QuoteReturnData)
Dim TempQuoteReturnFromExecuteEstimate As New QuoteReturnData

AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate)
AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate)
AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate)

每次都创建新对象

Dim AllEstimatesReturn As New List(Of QuoteReturnData)

AllEstimatesReturn.Add(New QuoteReturnData())
AllEstimatesReturn.Add(New QuoteReturnData())
AllEstimatesReturn.Add(New QuoteReturnData())

或者实现克隆QuoteReturnData的方法:

Class QuoteReturnData

    ' Creates an exact copy of the current QuoteReturnData object.
    Public Function SwallowCopy() As QuoteReturnData
        Return DirectCast(Me.MemberwiseClone(), QuoteReturnData)
    End Function

End Class

MemberwiseClone继承自Object,完全符合我们的要求;但是,此方法受到保护,只能在类中调用。因此我们将它包装成一个公共函数。

现在你可以这样做

Dim AllEstimatesReturn As New List(Of QuoteReturnData)
Dim TempQuoteReturnFromExecuteEstimate As New QuoteReturnData

AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate.SwallowCopy())
AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate.SwallowCopy())
AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate.SwallowCopy())

请注意,这只会创建一个浅层克隆。如果对象包含对其他对象的引用,则不会自动克隆这些其他对象。由您来决定这是否合适或是否需要深度克隆。

答案 2 :(得分:0)

对象存储在引用中。仅复制值类型(即结构)。

要获得对象的副本,您需要克隆它。除非您这样做,否则您将始终创建对同一对象的许多引用。你的清单也不例外。

我开始实现.NET Framework中存在的ICloneable接口。

更新

如果您不喜欢ICloneable界面,因为Clone()会返回键入为object的对象,您可以实现如下界面:

Public Interface ICloneable(Of T)
{
      Function Clone() As T;
}

将代码添加到列表中的代码看起来像这样(如果QuoteReturnData实现ICloneable(Of T),当然):

AllEstimatesReturn.Add(TempQuoteReturnFromExecuteEstimate.Clone());