Страница: 1 |
Страница: 1 |
Вопрос: Как правильно сохранить?
Добавлено: 11.09.04 13:45
Автор вопроса: danser | ICQ: 299287824
Dim T As New ArrayList()
Dim Str As String = "Sasha"
Dim Arr As New ArrayList()
Arr.Add(Str & Str)
T.Add(Str)
T.Add(Arr)
Dim B As New ArrayList()
B = CType(T.Clone, ArrayList)
Dim C As New ArrayList()
C.Add(B)
'теперь изменим масив Т
T.Item(0) = "Wasa"
CType(T.Item(1), ArrayList).Item(0) = "None"
With CType(C.Item(0), ArrayList)
MsgBox(CType(.Item(0), String))
'= "Saha"
MsgBox(CType(CType(.Item(1), ArrayList).Item(0), String))
'= "None"
End With
С етого кода можно увидеть что при изменении елементов масива Т изменяются по разному значения елементов масива С:
-Если мы изменим первый елемент(строку) масива Т->(T.Item(0) = "Wasa"), то это не отобразится на первом елементе(строке) масива С;
но стоить нам изменить второй елемент масива Т(тоже масив в котором мы изменим первый его елемент -> (CType(T.Item(1), ArrayList).Item(0) = "None")) то второй елемент масива С тоже будет изменен
ВОПРОС: Как присвоить масиву В масив Т так что би при последуещем изменении масива Т масив B(и соответственно масив С) не изменялся:
ТОБИШЬ должно быть:
With CType(C.Item(0), ArrayList)
MsgBox(CType(.Item(0), String))
'= "Saha"
MsgBox(CType(CType(.Item(1), ArrayList).Item(0), String))
'= "SashaSasha"
End With
Заранее благодарен за предположения по этому поводу.
Ответы
Всего ответов: 13
Номер ответа: 1
Автор ответа:
Павел
Администратор
ICQ: 326066673
Вопросов: 368
Ответов: 5968
Web-сайт:
Профиль | | #1
Добавлено: 12.09.04 07:17
А зачем нужен такой гемморой с кучей ArrayList'ов?
> то второй елемент масива С тоже будет изменен
Судя по коду, в объекте C только 1 элемент:
Dim C As New ArrayList()
C.Add(B)
Откуда там может взяться второй?
P.S. Некорректно называть ArrayList массивом. Массив - это класс
Array, объявляется массив примерно так:
Dim b(25) As String
А ArrayList - это коллекция.
Номер ответа: 2
Автор ответа:
danser
ICQ: 299287824
Вопросов: 76
Ответов: 209
Профиль | | #2
Добавлено: 12.09.04 11:39
Этот геморой нужен для обяснения проблемы, в чистом виде этот код не используется.
> то второй елемент масива С тоже будет изменен
-Имелось ввиду первый(запутаешся со словами, в коде более понятно)
Как сохранить обект Т в колекции С, чтобы при последуещем изменеии обекта Т эти изменеия не касались обекта сохраненного в колекции С?
Предложен вариант:
B=Ctype(T.Clone, ArrayList)
C.Add(B)
В примере видно что в одном случае это помагает но к сожалению только в одном...
Номер ответа: 3
Автор ответа:
Павел
Администратор
ICQ: 326066673
Вопросов: 368
Ответов: 5968
Web-сайт:
Профиль | | #3
Добавлено: 12.09.04 16:35
Как показало изучение потрохов ArrayList, метод Clone действует вполне
корректно:
'System.Collections.ArrayList.Clone
Public Overridable Function Clone() As Object Implements System.ICloneable.Clone
Dim _arrayList As System.Collections.ArrayList = New System.Collections.ArrayList(_size)
_arrayList._size = _size
_arrayList._version = _version
System.Array.Copy(_items, 0, _arrayList._items, 0, _size)
Return _arrayList
End Function
Он делает полную копию исходного объекта, копируя элементы из
внутреннего массива.
Далее... Если Вы меняете ссылку на объект в элементе коллекции, то на
исходном оъекте T это никак сказаться не должно:
T = New ArrayList
T.Add "a"
B=Ctype(T.Clone, ArrayList)
B(0) = "b"
Console.WriteLine T(0)
Но если меняется, к примеру, поле объекта-элемента, то эти изменения
будут видны в объекте T, так как метод Clone не создает копии
ссылочных элементов коллекции.
Public Class Test
Public a As String
End Class
'...
T = New ArrayList
Dim test As New Test
test.a = "a"
T.Add test
B=Ctype(T.Clone, ArrayList)
B(0).a = "b"
Console.WriteLine T(0).a
Вы это имели в виду?
Номер ответа: 4
Автор ответа:
danser
ICQ: 299287824
Вопросов: 76
Ответов: 209
Профиль | | #4
Добавлено: 12.09.04 17:48
Да мы это имели ввиду... только немножко измени(изменяется обект Т):
B=Ctype(T.Clone, ArrayList)
T(0).a = "b"
Console.WriteLine B(0).a
Как я понял ссылочние елементи колекции это всякого рода структуры (ArrayList, Structure, пользовательськие обекти...) и на ети елменти-обекты в колекции находятся только ссылки...
Но что мне делать если надо зафиксировать колекцию Т(и все ее елементы-обекти)?
Номер ответа: 5
Автор ответа:
Павел
Администратор
ICQ: 326066673
Вопросов: 368
Ответов: 5968
Web-сайт:
Профиль | | #5
Добавлено: 13.09.04 08:57
Можно для каждого элемента отдельно создавать копию:
Dim B As New ArrayList
For Each obj As Object In T
CType(B, IClonable).Add obj.Clone
Next
Тут только нужно повнимательнее рассмотреть вариант, если элемент
коллекции не реализует или неправильно реализует интерфейс IClonable.
Номер ответа: 6
Автор ответа:
danser
ICQ: 299287824
Вопросов: 76
Ответов: 209
Профиль | | #6
Добавлено: 13.09.04 09:28
Это вариант только одчасти решает проблему, я думал о нем, но если елементи обекты из колекци имеют довольно сложную структуру(в примере обект Тest имеет не одно поле типа String, а поле типа <Пользовательський обект> которий в совю очередь тоже имеет поле <Пользовательський обект> и так несколько раз) что тогда делать?
Номер ответа: 7
Автор ответа:
Павел
Администратор
ICQ: 326066673
Вопросов: 368
Ответов: 5968
Web-сайт:
Профиль | | #7
Добавлено: 13.09.04 09:50
Если все классы в этой структуре имеют атрибут Serializable, то можно
сериализовать и десериализовать объект. Тогда будет создана автономная
точная копия данных.
Номер ответа: 8
Автор ответа:
danser
ICQ: 299287824
Вопросов: 76
Ответов: 209
Профиль | | #8
Добавлено: 13.09.04 12:43
Да класи сереализированы. Это нужно для последуещего сохранения обекта в файле.
Но вроде метод Serializable должен иметь в аргументе обект типа FileStream которий в свою очередь связан с физическим файлом...предлагаешь использовать физический файл?...
как сохранить в другой(конкретного типа например Test) структуре(по возможности без использования физического файла)?
Номер ответа: 9
Автор ответа:
Павел
Администратор
ICQ: 326066673
Вопросов: 368
Ответов: 5968
Web-сайт:
Профиль | | #9
Добавлено: 13.09.04 14:01
Используй MemoryStream.
Номер ответа: 10
Автор ответа:
danser
ICQ: 299287824
Вопросов: 76
Ответов: 209
Профиль | | #10
Добавлено: 13.09.04 16:31
Какая ошибка?
До этого не пробывал работать с класом MemoryStream.
Чем инициализировать этот обект(MSDN нету- неоткуда пример постмотреть)?
dim T as new TSeansStatistic
...
Dim saveFile As MemoryStream
Dim BFormatter As New BinaryFormatter()
BFormatter.Serialize(saveFile, T)
Items_.Add(CType(BFormatter.Deserialize(saveFile), TSeansStatistic))
saveFile.Close
An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll
Additional information: End of Stream encountered before parsing was completed.
Если знаешь подкинь пожайлуста какой в этом случае должен быть код или пример с MSDN по MemoryStream.
Номер ответа: 11
Автор ответа:
danser
ICQ: 299287824
Вопросов: 76
Ответов: 209
Профиль | | #11
Добавлено: 13.09.04 16:33
Уточню: такая ошыбка для-
Dim saveFile As New MemoryStream()
Номер ответа: 12
Автор ответа:
Павел
Администратор
ICQ: 326066673
Вопросов: 368
Ответов: 5968
Web-сайт:
Профиль | | #12
Добавлено: 13.09.04 16:52
Мммммм.. У меня таких проблем не возникала.. Сейчас поищу кусок
рабочего кода из своих проектов...
Dim Stream As New IO.MemoryStream()
Dim formatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
formatter.Serialize(Stream, Errors)
Далее передвигаем позиию стрима в начало и десериализуем объект из
того же стрима. После этого стрим можно закрыть.
Номер ответа: 13
Автор ответа:
danser
ICQ: 299287824
Вопросов: 76
Ответов: 209
Профиль | | #13
Добавлено: 13.09.04 18:43
Да все так как ты говоришь- не передвинул позицию в начало..., а так все вроде получилось, сохраняет всю структуру что и требовалось доказать спасибо Павел что помог..., а то не знаю что бы я делал...