Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 | 3 | 4 |

 

  Вопрос: Тупой вопрос по структурам Добавлено: 28.09.12 22:40  

Автор вопроса:  Dark Engine | Web-сайт: www.wentas.2bb.ru | ICQ: 343191665 
Честно, мне очень стыдно, вопрос по матчасти, но раньше не сталкивался, а очень нужно. VB6
Необходимо обойти все поля структуры, количество которых заранее не известно, и получить строки с именами этих полей. Чтобы максимально конкретизировать вопрос, приведу НЕРАБОЧИЙ кусок кода, который очень прошу прокомментировать на момент возможности исправления и запуска:
Private Type UserType
Field1 As Integer
Field2 As Integer
...
Fieldn As Integer
End Type

Sub Process()
Dim A As UserType
B = Convert(A)
Debug.Print B
End Sub

Function Convert(Struct)
Result = ""
For Each Element In Struct
Result = Result + VarName(Element)
NEXT
Convert = Result
End Function


Итак, вопрос один в том, как можно обойти структуру (конструкция For Each не отрабатывает)? Вопрос второй, как получить имя поля при обходе (функции VarName, разумеется, не существует)?

Ответить

  Ответы Всего ответов: 56  

Номер ответа: 1
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #1
Добавлено: 29.09.12 16:27
стоит спросить себя - а зачем мне это?=) Может лучше подумать, как отказаться от такой задачи

Ответить

Номер ответа: 2
Автор ответа:
 Mikle



Вопросов: 5
Ответов: 134
 Профиль | | #2 Добавлено: 29.09.12 17:18
Можно вместо структур использовать классы, прописывать в них методы типа:
  1. Function GetFieldName(ByVal Index As Long) As String
  2. Function GetFieldCount() As Long

Ответить

Номер ответа: 3
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #3
Добавлено: 29.09.12 18:30
развивая эту тему. попробуйте подключить typelib information в references и выполнить подобный код для своего класса
  1. Private Sub Form_Load()
  2.     Dim test As New Class1
  3.     
  4.     Dim members As SearchResults
  5.     Set members = InterfaceInfoFromObject(test).members.GetFilteredMembers
  6.     
  7.     Dim i As Long
  8.     For i = 1 To members.Count
  9.         Debug.Print members(i).InvokeKinds, members(i).Name, , members(i).Hidden
  10.     Next i
  11. End Sub

Ответить

Номер ответа: 4
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #4
Добавлено: 29.09.12 18:32
http://www.vb6.us/tutorials/vb6-tutorial-build-scripting-language

Ответить

Номер ответа: 5
Автор ответа:
 Dark Engine



ICQ: 343191665 

Вопросов: 51
Ответов: 98
 Web-сайт: www.wentas.2bb.ru
 Профиль | | #5
Добавлено: 30.09.12 01:00
Winand пишет:
а зачем мне это?

Все очень просто. Структуры являются строками таблиц. Под структуру необходимо создать таблицу в БД, сделать отбор по определенным критериям при выборке из этой таблицы, но при этом, какая именно структура передается для конструирования запроса - заранее неизвестно. Как-то так. Хотя признаю, что саму идею обхода структур, равно как и получения имен полей, я попытался использовать исходя из схожести синтаксиса VB6 и 1С (в последнем такой номер прокатывает, причем там каждое поле имеет "ключ" (строка с именем поля) и "значение";).

Mikle пишет:
Можно вместо структур использовать классы

Ммм, можно конечно. Идея неплоха, но возникает вопрос, а не будет ли программа тормозить или неистово жрать ресурсы при использовании нескольких тысяч классовых объектов? Столько же структур вроде не перегружают проц и оперативу, но класс (насколько я знаю) ест ресурсов ощутимо больше структуры.

Ответить

Номер ответа: 6
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #6
Добавлено: 30.09.12 02:04
ключ-значение - это Collection в VB. Кроме того, существует объект Dictionary в библиотеке Microsoft Scripting Runtime. Это то же, что и коллекция, но шустрее, и умеет выдавать список всех ключей. Вот так:
  1. Dim dic As New Dictionary
  2. dic.Add "Field1", "deadbeef"
  3. dic.Add "Field8", "foodpr0n"
  4. Dim key As Variant
  5. For Each key In dic.Keys
  6.     Debug.Print key
  7. Next key


p.s. я в аудиоплеере описывал каждый трек в виде объекта, на нескольких тысячах программа совершенно не напрягалась:) конечно обращение к мемберам класса происходит медленее, чем к простым структурам.

Ответить

Номер ответа: 7
Автор ответа:
 Mikle



Вопросов: 5
Ответов: 134
 Профиль | | #7 Добавлено: 30.09.12 09:05
не будет ли программа тормозить или неистово жрать ресурсы при использовании нескольких тысяч классовых объектов

По сравнению со структурами - будет. Если это критично - можно в каждую структуру добавить одно лишнее поле ID, и заранее подготовить массив с атрибутами структур, где индекс соответствует ID.

Ответить

Номер ответа: 8
Автор ответа:
 Dark Engine



ICQ: 343191665 

Вопросов: 51
Ответов: 98
 Web-сайт: www.wentas.2bb.ru
 Профиль | | #8
Добавлено: 01.10.12 10:45
Winand пишет:
ключ-значение - это Collection в VB. Кроме того, существует объект Dictionary в библиотеке Microsoft Scripting Runtime. Это то же, что и коллекция, но шустрее, и умеет выдавать список всех ключей.

Коллекция, значит... это надо учесть. Спасибо большое! Буду разбираться. С коллекцией будет обращаться даже проще, чем со структурой и массивом, как предложил Mikle

Mikle пишет:
По сравнению со структурами - будет. Если это критично - можно в каждую структуру добавить одно лишнее поле ID, и заранее подготовить массив с атрибутами структур, где индекс соответствует ID.

А сами значения массива соответствуют именам полей? Мысль интересная, но, боюсь, с тем же успехом запросы составлять можно было бы и просто вручную по номерам полей (массив-то забивается вручную, иного хода не вижу в этом случае... а для автоматического забивания опять же нужно что-то вроде предложенных Winand'ом коллекций) и при программировании просто ставить жесткое соответствие. Наверное, не то решение, которое мне подходит, ведь я пытаюсь оптимизировать систему без потери скорости работы. Сейчас код загроможден запросами. Конструирование много времени не будет занимать, а если перевести систему на возможность динамического конструирования запросов - функционал программы может быть легко расширен без добавления новых запросов. Вот это и является моей задачей.

Ответить

Номер ответа: 9
Автор ответа:
 Mikle



Вопросов: 5
Ответов: 134
 Профиль | | #9 Добавлено: 01.10.12 13:44
Коллекции работают значительно медленнее структур.

Ответить

Номер ответа: 10
Автор ответа:
 Dark Engine



ICQ: 343191665 

Вопросов: 51
Ответов: 98
 Web-сайт: www.wentas.2bb.ru
 Профиль | | #10
Добавлено: 01.10.12 14:39
Mikle пишет:
Коллекции работают значительно медленнее структур.

Словари работают быстрее коллекций по словам Winand'а. Попробую их подтянуть. Но вот вопрос, если выбирать между коллекцией и классом, что быстрее работает?

Ответить

Номер ответа: 11
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #11
Добавлено: 01.10.12 15:31
коллекция - это встроенный класс:) Можно кстати напсиать класс-обёртку поверх Collection примерно так
  1. Option Explicit
  2. Private data As New Collection
  3. Private d_fields As New Collection
  4. Private d_cnt As Long
  5.  
  6. Public Sub Add(ByRef Value As Variant, ByRef Field As String)
  7.     data.Add Value, Field
  8.     d_fields.Add Field
  9.     d_cnt = d_cnt + 1
  10. End Sub
  11.  
  12. Public Function Value(ByRef Field As Variant) As Variant
  13.     If IsObject(data(Field)) Then _
  14.         Set Value = data(Field) _
  15.     Else Value = data(Field)
  16. End Function
  17.  
  18. Public Function Count() As Long
  19.     Count = d_cnt
  20. End Function
  21.  
  22. Public Function Fields() As Collection
  23.     Set Fields = d_fields
  24. End Function
  25.  
  26. Public Function Values() As Collection
  27.     Set Values = data
  28. End Function


А скорость надо тестировать. Может вас устроит и вариант выше. Но вообще, то, что вы хотите проще всего сделать Словарём.

Ответить

Номер ответа: 12
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #12
Добавлено: 01.10.12 15:38
Вот ещё такой вариант
  1. Option Explicit
  2. Private Type dataset
  3.     Fields() As String
  4.     Values() As Variant
  5. End Type
  6.  
  7. Private Sub Form_Load()
  8.     Const ITEMS As Long = 10
  9.     Dim data As dataset, i As Long
  10.     ReDim Preserve data.Fields(ITEMS - 1) As String
  11.     ReDim Preserve data.Values(ITEMS - 1) As Variant
  12.     For i = 0 To ITEMS - 1
  13.         data.Fields(i) = "Field" & i
  14.         data.Values(i) = i & "--val"
  15.     Next i
  16.     
  17.     For i = 0 To ITEMS - 1
  18.         Debug.Print data.Fields(i), , data.Values(i)
  19.     Next i
  20. End Sub

Ответить

Номер ответа: 13
Автор ответа:
 Dark Engine



ICQ: 343191665 

Вопросов: 51
Ответов: 98
 Web-сайт: www.wentas.2bb.ru
 Профиль | | #13
Добавлено: 01.10.12 16:13
Winand пишет:
А скорость надо тестировать.

Ну да. При шлифовке залью старую базу, там это будет заметно.
Winand пишет:
проще всего сделать Словарём.

Попробую и так и так. По итогам обработки больших объемов уже решу.
Winand пишет:
Вот ещё такой вариант

Думал уже об этом. Но есть сильный недочет к таком методе. Дело в том, что в рекорде поля идут разных типов. И фиг с ними, с числовыми, они худо-бедно с Variant совместимы. А что делать с датами и строками?

Ответить

Номер ответа: 14
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #14
Добавлено: 01.10.12 20:22
откуда такая мысль, что только числа совместимы с variant? что конкретно хранит Variant можно узнать с помощью VarType().

Ответить

Номер ответа: 15
Автор ответа:
 Dark Engine



ICQ: 343191665 

Вопросов: 51
Ответов: 98
 Web-сайт: www.wentas.2bb.ru
 Профиль | | #15
Добавлено: 01.10.12 23:07
Winand, видимо, из QB... с этим типом не экспериментировал, а может он явно больше. По поводу совместимости уже проверил, действительно даты и строки ест спокойно. Пардон, некоторые привычки еще c прошлого века утянул :D

Ответить

Страница: 1 | 2 | 3 | 4 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам