首页 > 解决方案 > 如何使用循环为集合中的多个不同变量赋值?

问题描述

我有一个问题一直困扰着我一段时间。考虑这段代码:

    Public Class Class1

        Dim VariableList as New List(of Object) From {MainForm.X, MainForm.Y,
     SettingsForm.Z, SettingsForm.Textbox1.Text} '...etc.

    Sub SetToZero()
        For Each Element in VariableList
            Element = 0
        Next
    End Sub

    Sub SetToCustomValue(value As Double)
        For Each Element in VariableList
            Element = value
        Next
    End Sub

    Sub LoadValuesFromFile()
        Dim path As String = MainForm.GetPath()

        For Each Element in VariableList
            Element = File.Readline()
        Next
    End Sub

    Sub SaveValuesToFile()
        Dim path As String = MainForm.GetPath()

        For Each Element in VariableList
            Element = File.Writeline()
        Next
    End Sub


    'and more similar functions/subs

如您所见,这个类所做的是将来自不同位置的许多不同变量放入一个集合中,然后各种函数使用循环读取或写入该集合中的每个变量的值。在这个例子中,我只有几个变量,但大多数时候有几十个。

读取值不是问题。编写它们是因为当我在类的顶部声明该变量列表时,该列表只是复制每个变量,而不是维护对它的引用。这意味着如果某个函数修改了该列表中的 MainForm.X,则实际变量 MainForm.X 不会被修改。要使用引用,我必须放弃循环,并在每个函数中手动分配每个变量。这显然是很多糟糕的代码。我只想声明该变量列表一次,然后使用循环,就像我上面写的这个示例代码一样。我的问题是,我怎样才能制作这样一个容器(列表、数组等)来保留对其中原始变量的引用,并使上面的代码成为可能?

标签: vb.netloopsvariablesreferencecontainers

解决方案


在 VB.NET 中存储指向变量的指针并不容易。作为一种解决方法,您可以使用类来存储变量,因为类始终用作指针。

ContainerClass这是一个使用拥有整数字典的方法来实现此目的的示例。这种方法的一个好处是您可以动态声明和命名“变量”。实际上,它们将被管理KeyValuePair。一旦你实例化了这个类的一个副本,你就可以通过使用这个类作为你的指针来使用它来“管理”你的变量。

我包含了一个循环,它将所有整数设置为相同的数字只是为了好玩,并演示最终会产生类似于您的问题中描述的效果的那种操作。

Public Class Form2
    'This is the container class which will be used to bypass the lack of pointers
    'if you wanted to change a property, like the window width, it would be more difficult, but simples variables will be no trouble
    Private variableContainer As New VariableContainer

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        variableContainer.AddVar("X", 5)
        variableContainer.AddVar("Y", 15)

        Debug.Print(variableContainer.GetVar("X"))
        Debug.Print(variableContainer.GetVar("Y"))

        variableContainer.SetAllVar(42)
        Debug.Print("Next line will print 42")
        Debug.Print(variableContainer.GetVar("X"))
    End Sub
End Class

Public Class VariableContainer
    'I know a public variable wouldn't need the fancy functions down there, but it's usually better to encapsulate, especially if you're working with a team
    'and "future you" count as a teammate, never forget that...
    Private list As New Dictionary(Of String, Integer)

    Public Sub AddVar(ByVal name As String, ByVal value As Integer)
        list.Add(name, value)
    End Sub

    Public Function GetVar(ByVal name As String) As Integer
        If list.ContainsKey(name) Then
            Return list(name)
        Else
            'I choose -1 arbitrarily, don't put too much thinking into this detail
            Return -1
        End If
    End Function

    Public Sub SetVar(ByVal name As String, ByVal num As Integer)
        If list.ContainsKey(name) Then
            list(name) = num
        End If
    End Sub

    Public Sub SetAllVar(ByVal num As Integer)
        Dim dict As New Dictionary(Of String, Integer)

        For Each item As KeyValuePair(Of String, Integer) In list
            dict.Add(item.Key, num)
        Next

        list = dict
    End Sub
End Class

玩得开心!


推荐阅读