【问题标题】:Can I force an object to be passed as "ByVal" (as a copy) in a call in .NET?我可以在 .NET 中的调用中强制将对象作为“ByVal”(作为副本)传递吗?
【发布时间】:2017-10-18 00:38:09
【问题描述】:

在下面的 VB.NET 代码中,我想将三个人添加到人员列表中。我认为我可以一遍又一遍地使用相同的人对象,并在下一次添加调用之前简单地更改它的名称。我希望每个调用都应该复制对象并将该副本添加到列表中......但我最终得到了一个包含三个“Kim”的列表。似乎列表元素引用的是同一个对象。

Class Person
    Public Name As String
End Class

Sub Foo()
    Dim Persons as New List(Of Person)
    Dim aPerson As New Person

    aPerson.Name = "John"
    Persons.Add(aPerson)
    aPerson.Name = "Emma"
    Persons.Add(aPerson)
    aPerson.Name = "Kim"
    Persons.Add(aPerson)
End Sub

我可以强制在每个 Add-call 中复制 aPerson 吗?还是我需要为 John、Emma 和 Kim 创建单独的对象?

【问题讨论】:

  • Or do I need to create separate objects for John, Emma and Kim? 是的,你必须这样做
  • 你应该给不同的对象。
  • 所有引用类型,即类,都以这种方式运行。如果Person 是一个结构,那么您显示的代码将会起作用,因为添加到列表中会创建一个副本。这可能会使在类上使用结构似乎是一个好主意,但事实并非如此。由于多种原因,类以这种方式工作,并且在适合类的情况下使用结构可能会导致许多问题。结构有它们的用途,但这通常只适用于小的、不可变的类型。绝大多数时间都应该使用类。这可能看起来很奇怪,但你会习惯的。
  • 但是为什么在 End Sub 之后销毁 aPerson 时对对象的引用没有销毁。毕竟似乎在某个地方存在对象的副本...在原始对象被销毁后存在的副本...?

标签: vb.net object pass-by-value


【解决方案1】:

你正在做的不是好习惯,因为你不应该那样使用一个类。

如果您的姓名来自列表等来源,您可以使用For Each 循环。

Dim MyNames As New List(Of String)
MyNames.Add("John")
MyNames.Add("Emma")
MyNames.Add("Kim")
For Each person_name As String In MyNames
    Dim aPerson As New Person
    aPerson.Name = person_name 
    Persons.Add(aPerson)
Next

如果数据来自文件、SQL 请求或 JSON,这种方法可能非常实用。

否则你只会有:

Dim Persons as New List(Of Person)
Dim aPerson As New Person
Dim bPerson As New Person
Dim cPerson As New Person
aPerson.Name = "John"
Persons.Add(aPerson)
bPerson.Name = "Emma"
Persons.Add(bPerson)
cPerson.Name = "Kim"
Persons.Add(cPerson)

【讨论】:

  • For 应该是 For Each。会提交一个编辑,但它的字符数限制,其余的答案都很好。
  • @AFriend 哈哈谢谢我完全忘了加,发帖的时候没注意
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 2020-09-23
  • 1970-01-01
  • 2013-02-20
  • 1970-01-01
相关资源
最近更新 更多