С Новым годом! Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1

End With по требованию

06.10.2024, 08:52. Показов 3019. Ответов 52
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В одном коде надо было перебирать элементы массива UDT и при определенных условиях "выпрыгнуть" из цикла, а после цикла при определенных условиях происходит редим этого массива, но обнаружилась одна проблемка с использованием оператора With в таком сценарии. Упрощенно проблемму можно воспроизвести таким кодом
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Private Type tpNode
    Val As Long
End Type
 
Sub TestWith()
    Dim i&, Nodes() As tpNode
    
    ReDim Nodes(5) As tpNode
    
    Do
        With Nodes(2)
            .Val = 1
            Exit Do
        End With
    Loop
    
    ReDim Preserve Nodes(6)    
End Sub
При выполнении данного кода после цикла выскочит ошибка "This array is fixed or temporarily locked". Она возникает по причине того, что оператор With захватывает элемен массива и блокирует массив от изменения размерности. Поскольку выход из цикла происходит до закрытия With, блокировка массива не снимается. В идеальном случае нужно было выходить из цикла после End With, но в том коде все действия происходят в условном операторе, помещенном внутри With. Здача данной темы отгадать, 1) как я реши эту пролему (или предложить свое решение); 2) то же самое, но с использованием цикла For )
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.10.2024, 08:52
Ответы с готовыми решениями:

Excel 2013 32-bit URLDownloadToFile пишет "Compile error: only comment may appear after End Sub End Function or End Prop
Добрый день! перепробовал все варианты и не вызывается функция URLDownloadToFile: пишет "Compile error: only comment may appear...

Требуется Web-разработчик (Front end/Back end) Санкт-Петербург
Обязанности: • Основная задача: бек энд разработка (организация REST-API сервисов и взаимодействие с БД (crud-операции) на python),...

Java Developer (front-end + back-end); Chicago,IL; H1B Sponsorship is available!
Valdi Group LLC is a Chicago based software development and software testing consulting firm that successfully delivering elegant and...

52
428 / 333 / 61
Регистрация: 29.06.2019
Сообщений: 493
06.10.2024, 09:55
Самое очевидное и простое решение - выкинуть With из кода как лишнее образование.
3
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
06.10.2024, 10:04  [ТС]
Цитата Сообщение от SergioJek Посмотреть сообщение
Самое очевидное и простое решение - выкинуть With из кода как лишнее образование.
При этом произойдет заметное замедление кода. Всякий раз, когда мы обращаемся к элементу массива (Nodes(i)) происходит вычисление указателя элемента по индексу, если у нас будет 2 обращения к одному и тому же элементу, то это время удваиваивается, если 3, то утраивается, в каждой итерации, а итераций может быть миллионы.
0
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
06.10.2024, 10:19
testuser2, это баг компилятора. Насколько я помню если выйти из With не через End With то элемент так и останется залоченным.
1
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
06.10.2024, 10:21  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
это баг компилятора
Кстати в подпрограмме если после Return нету такого бага
0
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
06.10.2024, 10:24
testuser2, я не проверял, но попробуй вручную вызвать SafeArrayUnlock, Но хз как поведет при выходе из процедуры, т.к. при выходе будет вызван Unlock.
1
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
06.10.2024, 10:51  [ТС]
The trick, я придумал как сделать без вызова Api, но может быть это бы помогло.
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
06.10.2024, 13:08
Цитата Сообщение от The trick Посмотреть сообщение
Насколько я помню если выйти из With не через End With
может через Exit With

Добавлено через 37 секунд
а Exit With вообще есть?

Добавлено через 1 минуту
Цитата Сообщение от testuser2 Посмотреть сообщение
а итераций может быть миллионы
даже если и миллионы, не думаю что работа твоей программы сильно замедлится, максимум на пол секунды дольше подождёшь и всё

Добавлено через 1 минуту
ты приведи доказательства мне по скоростям с реальными примерами и с доказательством необходимости этого With.
Соглашусь с SergioJek что скорее всего With просто напросто не нужен вообще.

Добавлено через 3 минуты
А вот кстати и решение:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Option Explicit
Dim Nodes() As tpNode
 
Private Type tpNode
    Val As Long
End Type
 
Sub TestWith()
    ReDim Nodes(5) As tpNode
    
    Do
        With Nodes(2)
            .Val = 1
            Exit Sub
        End With
    Loop
End Sub
 
Private Sub Form_Load()
    TestWith
    ReDim Preserve Nodes(6) ' Вызвать после процедуры, а из процедуры делать выход в конструкции With
End Sub
Добавлено через 57 секунд
Exit With не существует, я проверил

Добавлено через 7 минут
The trick, SafeArrayUnlock не помог кстати
2
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
06.10.2024, 13:38  [ТС]
Даю подсказку: я использовал Goto и расположил With не внутри, а снаруже цикла
0
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
06.10.2024, 13:49
testuser2, я тебе дал ответ уже как всё работает
0
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
06.10.2024, 16:15  [ТС]
Лучший ответ Сообщение было отмечено HackerVlad как решение

Решение

HackerVlad, это не подходит, надо редимить в той же процедуре после цикла с выходом из With

Добавлено через 20 минут
Итак, вот мое решение. Сделал несколько итераций, чтобы было понятней, как это работает
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
WithElem:
    With Nodes(i)
      GoTo Cycle
      Do
          GoTo WithElem
Cycle:
          i = i + 1
          If i < 5 Then
              .Val = i
          Else: Exit Do
          End If
      Loop
    End With
    
    ReDim Preserve Nodes(6)
Добавлено через 9 минут
Есть еще вариант вместо Exit Do использовать флаг выхода из цикла, но тогда при каждой итерации будет проверка флага, но, что-то подсказывает, что 2 перехода на метки будут быстрей чем одна проверка флага

Добавлено через 20 минут
А так будет работать с циклом For. У цикла For нужно обязательно пройти "шапку", чтобы цикл запустился
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    GoTo StartCycle
WithNode:
    With Nodes(i)
      GoTo Cycle
StartCycle:
      For i = 1 To 5
          GoTo WithNode
Cycle:
          If i < 5 Then
          .Val = i
          Else: Exit For
          End If
      Next
    End With
Добавлено через 13 минут
Тут можно заметить, что открытий With в цикле происходит много, в то время как закрытие одно в обоих случаях, однако это нормально работает, что наверное можно объяснить тем, что для одного итого же With используется всегда одна и та же веменная переменная и именно освобождение этой переменной играет роль.

Добавлено через 5 минут
Причем эта переменная, наверняка, работает по принципу ByRef-ссылки и ее можно использовать для работы с указателями, только вопрос как найти ее указатель..

Добавлено через 39 минут
Кажись нашел, она идет сразу перед стеком аргументов..

Добавлено через 1 минуту
Точнее не аргументов, а переменных процедуры

Добавлено через 7 минут
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Sub TestWith2(Optional ByVal lp0&)
    Dim Nodes(2) As tpNode, Node As tpNode, pTmp&
    pTmp = VarPtr(pTmp) - 4
    
    With Node
        CopyMemory ByVal pTmp, VarPtr(Nodes(0)), 4
        .Val = 1
        CopyMemory ByVal pTmp, VarPtr(Nodes(1)), 4
        .Val = 2
        CopyMemory ByVal pTmp, VarPtr(Nodes(2)), 4
        .Val = 3
    End With
    Debug.Print Nodes(0).Val & vbCr & _
                Nodes(1).Val & vbCr & _
                Nodes(2).Val
End Sub
Добавлено через 20 минут
Если несколько with-ов, то первый будет по адресу VarPtr(pTmp) - 4, второй VarPtr(pTmp) - 8 и т.д.

Добавлено через 6 минут
Который первы в коде (самый верхний With) будет VarPtr(pTmp) - 4, а дальше которые ниже по коду -8, -12
0
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
07.10.2024, 05:08  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
2 перехода на метки будут быстрей чем одна проверка флага
Неа, ни какой разницы такой код стольже быстрый как из с метками
Visual Basic
1
2
3
4
5
6
7
8
9
      Do
          With Nodes(i)
            i = i + 1
            If i < 5 Then
                .Val = i
            Else: stopIter = True
            End If
          End With
      Loop Until stopIter = True
Добавлено через 13 минут
Разница есть но всего 2-5% на обработке 1 млн.
Кликните здесь для просмотра всего текста
2,888672
2,859375
2,875

2,753906
2,734375
2,734375


Добавлено через 3 часа 8 минут
Цитата Сообщение от testuser2 Посмотреть сообщение
А так будет работать с циклом For
Там не правильно, вот прально
Visual Basic
1
2
3
4
5
6
7
8
9
    For i = 1 To 5
        With Nodes(i)
          If i < 5 Then
              .Val = i
          Else
              i = 5 'Exit For
          End If
        End With
    Next
1
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
07.10.2024, 09:34
Хм... век живи - век учись. Я до сих пор считал, что With - это просто синтаксический сахар, сокращение длинных выражений. Для того, чтобы повысить быстродействие, убрав постоянные расчёты индексов, применял процедуры.
2
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
08.10.2024, 02:28  [ТС]
Mikle Quits, Как вы сделали такое выделение With в тексте?
Цитата Сообщение от Mikle Quits Посмотреть сообщение
Для того, чтобы повысить быстродействие, убрав постоянные расчёты индексов, применял процедуры.
Фактически можно также считать решением вопроса. Еще можно тело цикла поместить в подпрограмму и выход из подпрограммы (Return) корректно будет завершать With.
0
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
08.10.2024, 08:19
Цитата Сообщение от testuser2 Посмотреть сообщение
Как вы сделали такое выделение With в тексте?
Тег "InLine".
Цитата Сообщение от testuser2 Посмотреть сообщение
Еще можно тело цикла поместить в подпрограмму и выход из подпрограммы
Но это не избавляет от With, а только корректно завершает. Простое перемещение цикла внутрь блока With тоже решает эту проблему, и не нужны устаревшие конструкции.
А процедура именно заменяет With, причём, как удаляет постоянные расчёты индексов, так и сокращает написание выражений.
1
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
08.10.2024, 16:41
Цитата Сообщение от testuser2 Посмотреть сообщение
Return)
в vb6 нет оператора continiue или return
0
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
08.10.2024, 17:55  [ТС]
HackerVlad, Return есть, это секретный оператор, используется с еще одним секретным оператором GoSub, но речь уже его касалась в этой теме. Может пример так себе, но просто для примера как его можно использовать.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    GoTo InWith
WithNode:
    With Nodes(i)
Return
InWith:
      
      Do
          GoSub WithNode
          If i < 5 Then
              i = i + 1
              .Val = i
          Else
              Exit Do
          End If
      Loop
      
      l = Rnd * 5
      For i = 1 To 5
          GoSub WithNode
          If i = l Then .Val = l: Exit For
      Next
    
    End With
1
Испарился
 Аватар для HackerVlad
1741 / 637 / 45
Регистрация: 10.09.2021
Сообщений: 2,769
08.10.2024, 18:44
странно
0
1382 / 838 / 89
Регистрация: 08.02.2017
Сообщений: 3,510
Записей в блоге: 1
09.10.2024, 04:49  [ТС]
Имхо это удобно, тем, что позволяет некоторые участки процедуры определить подпрограммой (термин из qbasic мне в школе о нравился) и испоизовать в разных частях процедуры. У подпрограмм есть свой стек вызовов и если внутри подпрограммы вызвать другую подпограмму, то она вернется туда, от куда ее вызвали и та из которой вызвали вернется, откуда ее вызвали

Добавлено через 5 минут
Есть еще одно секретное слово в бейсике, как Let, правда оно не имеет особого значения )
0
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
20.11.2024, 09:27
Наткнулся на неприятный баг With.
На форме frmMain есть пикчербокс picScore. Из модуля делаю с ним различные действия:
Visual Basic
1
2
3
4
5
    frmMain.picScore.CurrentX = 2
    frmMain.picScore.CurrentY = 32 * i - 4
    frmMain.picScore.Print PlName(i);
    frmMain.picScore.CurrentX = 216
    frmMain.picScore.Print Trim(Str(PlScore(i)));
Если обрамить это всё в With frmMain.picScore, укорачивается:
Visual Basic
1
2
3
4
5
    .CurrentX = 2
    .CurrentY = 32 * i - 4
    .Print PlName(i);
    .CurrentX = 216
    .Print Trim(Str(PlScore(i)));
Но псевдометод .Print не работает.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.11.2024, 09:27
Помогаю со студенческими работами здесь

Syntax error unexpected $end and premature end-of-file единственный варнинг
Помогите исправить!! Device (FWH) { Name (_HID, EisaId (&quot;INT0800&quot;)) Method (_CRS, 0,...

Ведущие разработчики .NET (C#) Front-end и Back-end (Москва, не аутсорс)
В департамент разработки ПО крупной международной компании требуются: Lead Back-end developer: -Опыт разработки программного...

Error при создании .obj файла 85:End of file, no end directive
Добрый день! помогите разобраться с ошибкой! Компилирую следующий код в ibm personal computer macro assembler v 2.0: TITLE ...

With myChart With .Axes(xlCategory) .CategoryType = xlTimeScale .BaseUnit = xlseconds End With End With
MSDN утверждает: BaseUnit Property Applies To Axis object. Description Returns or sets the base unit for the specified category...

Работа в Германии (Front-End, Back-End или Full-Stack)
Ребят,я понимаю, реклама вас задолбала,но все-же, поступил заказ в наше агентство из Германии они ищут программиста.Работа в Германии,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru