Хранение и восстановление 2-мерного массива в классе - PullRequest
1 голос
/ 21 марта 2019

Я только недавно перешел с VB6 на VB.NET, и я перекодирую старое приложение. Так что я пока не очень разбираюсь в .NET.

У меня есть несколько (скажем, 4 в этом примере кода) двумерных строковых массивов (или фактически массив массивов), которые я хочу сохранить как элементы ComboBox, т.е. один двумерный массив - это один элемент.

Public Class MyItem

    Private sName As String
    Private sArr As Array()

    Public Sub New(ByVal Name As String, ParamArray Arr As Array())
        sName = Name
        sArr = Arr
    End Sub

    Public Property Arr() As Array()
        Get
            Return sArr
        End Get

        Set(ByVal sValue As Array())
            sArr = sValue
        End Set
    End Property

    Public Overrides Function ToString() As String
        Return sName
    End Function

End Class

---

Dim sMyArray as Array()

For i As Integer = 0 to 3
    sMyArray = Nothing   ' resetting the array before refilling it
    '
    ' No code here but filling sMyArray by reading a text file, each line
    ' number as dim 1 and splitted each line into dim 2 with ";" using Split(sRead, ";")
    ' so Debub.Print(sMyArray(0)(0)) prints the beginning of the first line until first ";" <- this works fine
    '
    ' Then passing sMyArray to a ComboBox item
    ' 
    ComboBox.Items.Add(New MyItem("item" & i, sMyArray))
Next i

Проблема в том, что при восстановлении массивов из элементов ComboCox только последний элемент ComboBox имеет данные массива . Так например

Dim sMyNewArray As Array() = ComboBox.Items.Item(0).Arr
Debug.Print(sMyNewArray(0)(0))

выдает ошибку, в то время как

Dim sMyNewArray As Array() = ComboBox.Items.Item(3).Arr
Debug.Print(UBound(sMyNewArray(UBound(sMyNewArray))))

не распознает и печатает последнюю строку последнего элемента

Может кто-нибудь выяснить, что мне не хватает, или сказать мне лучший способ сделать это? Я почти уверен, что есть один ..

Ответы [ 2 ]

2 голосов
/ 21 марта 2019

Я не уверен на 100%, но я думаю, что проблема в этом разделе:

Dim sMyArray as Array()

For i As Integer = 0 to 3
    sMyArray = Nothing   ' resetting the array before refilling it

Массивы технически являются ссылочными типами, но, как и строки, есть некоторая дополнительная магия компилятора, чтобы они иногда воспринимались как типы значений, и у меня есть ощущение, что в этом случае использовалась фактическая ссылка sMyArray (возможно, из-за ParamArrays оптимизация), так что установка на Nothing сломала вещи. Более идиоматический способ написать этот код для .Net это так:

For i As Integer = 0 to 3
    Dim sMyArray as Array()

.Net имеет гораздо более сложный сборщик мусора, чем был доступен для VB6. Мы уже не часто устанавливаем переменные на Nothing, но вместо этого просто переназначаем их или позволяем им выпадать из области видимости. Фактически, установка переменной на Nothing может в редких случаях быть активно вредной. Более того, мы хотим видеть ключевое слово Dim внутри цикла, поэтому вы работаете с различной переменной на каждой итерации с наименьшей возможной областью действия.

Пока я здесь, в .Net мы в значительной степени никогда не используем базовый тип Array. Вместо этого:

Private sArr As Array()

Вы в значительной степени всегда делаете это:

Private arr As String()()

или это для истинных двумерных (не зубчатых) массивов:

Private arr As String(,)

или, что лучше всего, это:

Private arr As New List(Of String())

Поскольку VB.Net имеет больше типов коллекций, чем просто массив.

Кроме того, у меня нет удобной ссылки, но руководящие принципы Microsoft по кодированию теперь прямо просят вас , а не использовать венгерские бородавки для имен переменных и классов (поэтому sArr может быть просто arr) , Это изменение эпохи VB6 из-за изменений в языке, где тип, скорее всего, неявно связан с переменной, и улучшений в инструментах, где префиксы обычно больше не добавляют много полезности и, как было показано, ухудшают читабельность.

0 голосов
/ 21 марта 2019

Не совсем уверен, почему у вас есть двумерный массив, но вот небольшой пример, НЕ использующий тип Array. Он использует только простые строки и строковые массивы. Позвольте мне знать, если это помогает. Это разбивает несколько строк, затем считывает результаты после заполнения.

Public Class Form1



    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim sMyArray()() As String

        Dim line1 As String = "a;b;c;d 1;2;3;4;5"
        Dim line2 As String = "z;x;y;w 99;65;32;21;18"

        sMyArray = ParseString(line1)
        cboBox1.Items.Add(New MyItem("System0", sMyArray))

        sMyArray = ParseString(line2)
        cboBox1.Items.Add(New MyItem("System1", sMyArray))

        For i As Integer = 0 To cboBox1.Items.Count - 1

            For j As Integer = 0 To UBound(cboBox1.Items(i).arr)
                For k As Integer = 0 To UBound(cboBox1.Items(i).arr(j))
                    Debug.Write(cboBox1.Items(i).arr(j)(k) & " ")
                Next

            Next
            Debug.WriteLine("")
        Next

    End Sub

    Private Function ParseString(s As String) As String()()
        Dim rows As String() = s.Split(" ")
        Dim matrix As String()() = New String(rows.Length - 1)() {}

        For i As Integer = 0 To rows.Length - 1
            matrix(i) = rows(i).Split(";")
        Next

        Return matrix

    End Function
End Class

Public Class MyItem

    Private sName As String
    Private sArr As String()()


    Public Sub New(ByVal Name As String, ByVal ParamArray Arr As String()())
        sName = Name
        sArr = Arr
    End Sub

    Public Property Arr() As String()()
        Get
            Return sArr
        End Get

        Set(ByVal sValue As String()())
            sArr = sValue
        End Set
    End Property

    Public Overrides Function ToString() As String
        Return sName
    End Function

End Class
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...