我的洞应用程序有一个Data类。此数据类可以从应用程序中的许多其他类进行访问。我在开头加载数据,并希望数据不会全局更改。
这就是它现在的样子(例子)
NotInheritable Class Data
Public NotInheritable Class Country
Public CounCode As String = String.Empty
Public ISOCode As String = String.Empty
Public Name As String = String.Empty
Public Overrides Function ToString() As String
Return CounCode + ": " + ISOCode + " - " + Name
End Function
End Class
Private Shared m_Countries As List(Of Country) = Nothing
Public Shared ReadOnly Property Countries As List(Of Country)
Get
Return m_Countries
End Get
End Property
Shared Sub New()
m_Countries = New List(Of Country)
Dim Country As Country = New Country
Country.Name = "Germany"
m_Countries.Add(Country)
Country.Name = "Italy"
m_Countries.Add(Country)
Country.Name = "Spain"
m_Countries.Add(Country)
End Sub
结束班
但是当我喜欢这个时
Dim countries As List(Of Data.Country) = Data.Countries
countries(0).Name = "Hello World"
Dim countries2 As List(Of Data.Country) = Data.Countries
MessageBox.Show(countries(0).Name + " - " + countries2(0).Name)
我怀疑“Hello World - Germany”,但我会得到“Hello World - Hello World”。 为什么我可以 - 全球 - 改变财产?以及如何解决这个问题? 我想允许其他类更改国家/地区的名称,但不能更改全局。
此致
答案 0 :(得分:0)
集合属性是只读的 - 不是集合本身,而不是集合中的项目。您尚未将集合重新分配给新集合,该集合是只读字段或属性访问器阻止的唯一事物。它运作正常。
只有一个集合属性才能不使集合本身成为只读(您仍然可以添加/删除/等),并且不制作项目中的项目集合只读。对于只读集合:请尝试ReadOnlyCollection<T>
。对于项目本身:您必须将Country.Name
设为只读。
你不能做什么(在构造函数之外)是:
Data.Countries = New List(Of Country)
答案 1 :(得分:0)
正如马克所说,没有办法阻止这一点。您不能为属性分配不同的集合,但可以更改属性封装的集合(添加/删除/更改)
解决方法如下:
Imports System.Linq
Module StartupModule
Sub Main()
Dim users As New List(Of User) From {
New User() With {.Name = "John"},
New User() With {.Name = "Nick"}
}
Dim company As New Company(users)
Console.WriteLine("names before change")
For Each u In company.Users
Console.WriteLine(u)
Next
Console.WriteLine()
Console.WriteLine("change names")
For Each u In company.Users
u.Name = "something else"
Next
Console.WriteLine()
Console.WriteLine("names after change")
For Each u In company.Users
Console.WriteLine(u)
Next
Console.ReadLine()
End Sub
Public Class Company
Private _users As New List(Of User)
Public Sub New(users As List(Of User))
Me.Users = users
End Sub
Public Property Users As List(Of User)
Get
Return (From u In _users
Select DirectCast(u.Clone, User)).ToList
End Get
Private Set(value As List(Of User))
_users = value
End Set
End Property
End Class
Public Class User
Implements ICloneable
Public Property Name As String
Public Overrides Function ToString() As String
Return Name
End Function
Public Function Clone() As Object Implements ICloneable.Clone
Return New User() With {.Name = Name}
End Function
End Class
End Module
属性的getter总是返回原始对象的克隆集合。因此,您必须为您的类实现ICloneable
,或者只是创建一个函数来返回对象的克隆。
这样,更改将在克隆集合中进行,而不是更改实际对象。
该方法的缺点是,无论何时引用集合(在示例中为Company.Users
集合),都会创建一个新列表,其中包含原始项目的克隆。