Должен ли я использовать ключевое слово Call в VB / VBA?

42

Я использую ключевое слово Call при вызове subs в VB/VBA. Я знаю, что это необязательно, но лучше ли использовать его или оставить его? Я всегда думал, что это было более явным, но, возможно, это просто шум.

Кроме того, я читаю это на другом форуме: использование ключевого слова Call выполняется быстрее, потому что он знает, что он не будет возвращать какие-либо значения, поэтому ему не нужно настраивать любое стековое пространство, чтобы освободить место для возврата значение.

  • 11
    В некоторых случаях использование ключевого слова call довольно полезно, например, когда вы просто хотите использовать класс один раз. Я использую его сегодня для генерации случайного солевого Call New RNGCryptoServiceProvider().GetBytes(salt) без Call Я бы сначала использовал переменную RNGCryptoServiceProvider
  • 1
    Это, пожалуй, лучшая (если не единственная) причина использовать вызов, о котором я когда-либо слышал.
Теги:
call
vb6

9 ответов

23

Ага. Я давно задумывался об этом, и даже чтение двухдюймовой книги на VBA в основном говорит, что не используйте его, если вы не хотите использовать функцию Найти VBE, чтобы легко находить вызовы в больших проектах.

Но я просто нашел другое применение.

Мы знаем, что возможно объединить строки кода с символом двоеточия, например:

Function Test(mode as Boolean) 
    if mode = True then x = x + 1 : Exit Sub
    y = y - 1
End Sub

Но если вы делаете это с вызовами процедур в начале строки, VBE предполагает, что вы ссылаетесь на метку и удаляет любые отступы, выравнивая строку до левого поля (даже если процедура вызывается как предполагаемая ):

Function Test()
Function1 : Function2
End Function

Использование оператора Вызов позволяет конкатенацию вызовов процедур при сохранении отступов кода:

Function Test()
    Call Function1 : Call Function2
End Function

Если вы не используете оператор Вызов в приведенном выше примере, VBE предположит, что "Function1" - это метка и выровнять по левому краю в окне кода, даже если он не будет вызывают ошибку.

  • 14
    +1 для случая легитимного изображения ... хотя я бы сказал, что использование нескольких команд / вызовов функций в одной строке - плохая практика.
11

Для VB6, если есть вероятность, что он будет преобразован в VB.NET, использование Call означает, что синтаксис не изменяется. (Скобки в VB.NET требуются для вызовов методов.) (Я лично не считаю, что это стоит того, что любой конвертер .NET, по крайней мере, сможет поместить в круглые скобки, когда это необходимо. Я просто перечисляю его как причина.)

В противном случае это просто синтаксический сахар.

Обратите внимание, что ключевое слово Call, скорее всего, не будет быстрее при вызове какого-либо другого метода/функции, потому что функция все равно возвращает свое значение, а VB не нужно создавать локальную переменную для ее получения, даже если Call не используется.

  • 0
    В некоторых случаях это не просто синтаксический сахар. Смотрите мой ответ на высшем уровне.
10

Я всегда использую Call в VBA. Для меня это выглядит просто чище. Но, я согласен, это просто синтаксический сахар, который ставит его прямо в сферу личных предпочтений. За последние несколько лет я встретил, вероятно, дюжину парней VBA, и ни один из них не использовал Call. Это имело дополнительное преимущество, что я всегда знал, какой код был моим.: Р

  • 0
    Это, конечно, не просто синтаксический сахар в некоторых случаях. Смотрите мой ответ на высшем уровне.
5

Нет, он просто добавит 7 символов за вызов без какой-либо выгоды.

  • 0
    Это неверно. В некоторых случаях это имеет драматический эффект. Смотрите мой ответ на высшем уровне.
3

Если вы читаете страницу поддержки MSDN для Statement Statement, для конкретного случая o VBA, по крайней мере, он говорит, что Вызов не является обязательным, но что очень важно, и никто, кажется, не заметил, это цитата:

"Если вы используете синтаксис Call для вызова любой внутренней или пользовательской функции, возвращаемое значение функции отбрасывается."

Вот почему Вызов далеко не бесполезен. Предположим, вы пишете Sub SupportTasks, который делает для вас очень важные материалы для основного раздела (например, он импортирует данные из файла, который будет использоваться различными процедурами). Теперь обратите внимание, что, поскольку SupportTasks читает внешние данные, всегда есть вероятность, что эти данные не будут стандартными, а суб не сможет выполнять свою роль. Что вы делаете?

Вы можете, например, использовать логические функции, которые возвращают False, если что-то пойдет не так. Вместо вызова sub вызовите функцию SupportTasks внутри и If, которая выйдет из Main sub, если есть аномалия:

If Not SupportTasks(SomeArgument) Then
    Application.ScreenUpdating = True
    Exit Sub
'Else continue the Main sub regularly without writing anything in here
End If

Если вам интересно, как это связано с Вызов, рассмотрите следующее: в другом подпроцессе я вызываю SupportTasks, но мне не нужно его возвращаемое логическое значение (например, Я уверен, что ошибка не произойдет). Ну, если я не помещаю его в оператор If или не назначаю функцию бесполезной переменной, VBA не будет компилировать и не возвращать мне ошибку (вызов процедуры недействителен бла-бла-бла должен присваивать значение чему-то бла-бла-бла). Что там, где Вызов входит, чтобы сохранить день!

Call SupportTasks(SomeArgument) '<< "Call Function" call doesn't return an error

Если вы все еще считаете это бесполезным, подумайте об этом как о ресурсе, чтобы оставаться организованным. Написание отдельных процедур для подпрограмм, разделяемых многими процедурами, делает ваш код короче и более понятным, особенно когда вы пишете действительно большие приложения. Например, ERP, построенный на основе интеграции Excel-Access, может быть проще в эксплуатации, ремонте и настройке, если ваш ИТ-отдел медленно доставляет/реализует реальную систему...

В заключение, некоторые интернет-мудрости:

Всегда пишите свой код, как если бы человек, который его рассмотрит, является убийственным психопатом, который знает, где вы живете.

Аминь.

  • 4
    Вы можете просто использовать SupportTasks SomeArgument и он прекрасно компилируется без использования Call .
  • 0
    Это правда. Он просто игнорирует возвращаемое значение. Полагаю, это немного смещает мое эссе, нет? ...
Показать ещё 1 комментарий
3

Я использую Call для всех VBA-разработок общих функций библиотеки, которые я, возможно, буду использовать в VB.NET. Это позволяет мне перемещать код с помощью копирования и вставки между всеми вкусами VB. Я делаю это, чтобы избежать ошибок синтаксиса, создаваемых редактором кода, когда он "форматирует" или "красиво печатает" вставленный код. Единственными изменениями обычно являются включение/исключение оператора Set.

Если вы не планируете переводить код VB/VBA на VB.NET, тогда нет необходимости использовать оператор Call.

  • 0
    Нет, не обязательно (не «нет необходимости»). В некоторых случаях это имеет драматический эффект. Смотрите мой ответ верхнего уровня ниже.
1

Единственный случай, когда я нашел "вызов", полезен - это случайность, касающаяся некоторых специальных операторов.

Dim c As IAsyncOperation(Of StartupTask) = StartupTask.GetAsync("Startup")
……
(Await c).Disable()

Я получил синтаксическую ошибку для второй строки, точно так же, как вы получите с оператором "New". Я действительно не хочу новую переменную, которая слишком не элегантна для меня. Итак, я попробовал:

DirectCast(Await c, StartupTask).Disable()

Это синтаксически правильно. Но затем IDE намекнул, что "DirectCast" не нужен, и дал упрощение. Да, это:

Call (Await c).Disable()

Вот почему я люблю VS2017 Preview.

1

Я опаздываю на вечеринку на 7 лет, но я просто случайно встретил ключевое слово Call несколько минут назад, читая что-то в MSDN. В частности, он использовался для выполнения чего-то, что, как я думал, невозможно в VB.NET(в отличие от С#), что связано с ответом @FCastro.

Class Test
    Public Sub DoSomething()
        Console.WriteLine("doing something")
    End Sub
End Class

Sub Main()
    Call (New Test()).DoSomething()
End Sub

В нечетном случае вам не нужен фактический экземпляр объекта, но требуется один из его методов, вы можете использовать Call для сохранения строки. Обратите внимание, что это необязательно, если это правая часть операции:

Class Test
    Public Function GetSomething() As Integer
        Return 0
    End Function
End Class

Sub Main()
    Dim x As Integer = (New Test()).GetSomething()
End Sub
  • 1
    Веселье! Часть меня хочет попробовать это, другая часть меня боится выучить еще одну вредную привычку :-)
  • 0
    @SlowLearner Я предлагаю просто держать это в вашей шляпе как пустяки. VB создает достаточно вредных привычек, как оно есть :)
Показать ещё 1 комментарий
0

Старый поток, но я не вижу, чтобы кто-то охватывал это важное различие: в некоторых (распространенных) ситуациях Call не позволяет скобкам вокруг аргументов функции (и под) вызывать строгую интерпретацию аргументов как ByVal.

Большой вывод для вас заключается в том, что если вы действительно используете круглые скобки вокруг аргументов процедуры, возможно, наизусть или по привычке, даже если они не требуются, то вы ДОЛЖНЫ ИСПОЛЬЗОВАТЬ Call, чтобы гарантировать, что подпрограмма неявного или явного ByRef не будет проигнорирована в пользу ByVal; или, вместо этого, вы должны использовать присваивание "знака равенства" возвращаемого значения для предотвращения игнорирования (в этом случае вы не будете использовать Call).

Опять же, это должно защитить вас от неблагоприятного получения ByVal от рутины. И наоборот, если, конечно, вы ХОТИТЕ интерпретацию ByVal независимо от объявления процедуры, тогда ВЫКЛЮЧИТЕ вызов (и используйте скобки).

Обоснование: обобщение https://msdn.microsoft.com/en-us/library/ee478101%28v=vs.84%29.aspx "Параметры ByRef и ByVal"

Если
1. есть назначение возврата вызова функции, например
iSum = myfunc (myArg)
или же
2. "Call" используется, например,
позвоните myFunc (myArg)
или же
позвоните mySub (myArg)

тогда круглые скобки строго разграничивают список вызывающих аргументов; объявление процедуры определяет ByVal или ByRef. В противном случае скобки заставляют ByVal использоваться подпрограммой - хотя ByVal не был указан в подпрограмме. Таким образом,
mySub (myArg) 'использует ByVal независимо от объявления процедуры
в то время как
Вызов mySub (myArg) использует ByRef, если подпрограмма не объявляет ByVal

Также обратите внимание, что Call синтаксически требует использования скобок. Вы можете пойти
mySub myArg
но ты не можешь идти
позвоните mySub myArg
но вы можете пойти
позвоните mySub (myArg)
(и синтаксически необходимы скобки для присвоения возвращаемого значения функции)

ВНИМАНИЕ, однако, что ByVal в объявлении процедуры отменяет все это. И к вашему сведению, ByRef всегда подразумевается в декларации, если вы молчите; Таким образом, TMK ByRef не имеет очевидного значения, кроме документального.

Повторение сверху: большой вывод для вас заключается в том, что если вы действительно используете круглые скобки вокруг аргументов процедуры, возможно, наизусть или по привычке, даже если они не требуются, тогда вы ДОЛЖНЫ ИСПОЛЬЗОВАТЬ Call, чтобы гарантировать, что подпрограмма неявного или явного ByRef будет не игнорируется в пользу ByVal; или, вместо этого, вы должны использовать присваивание "знака равенства" возвращаемого значения для предотвращения игнорирования (в этом случае вы не будете использовать Call).

Опять же, это должно защитить вас от неблагоприятного получения ByVal от рутины. И наоборот, если, конечно, вы ХОТИТЕ интерпретацию ByVal независимо от объявления процедуры, тогда ВЫКЛЮЧИТЕ вызов (и используйте скобки).

  • 0
    Этот ответ, конечно, не новаторский. Если у вас есть привычка ставить круглые скобки вокруг аргументов, когда вы не должны, вам следует остановиться , а не прибегать к ключевому слову Call
  • 0
    Замечательно, что вы это знаете, но спросите 20 лучших практиков VBA, которых вы можете найти, и 2 узнают об этом. Даже если я ошибаюсь, и это 4 из 20, которые знают это, это только потому, что они были сожжены этим сверхтонким нежелательным ByVal-ing (и они заметили "повреждение"). Более того, в моем обширном наблюдении почти все привыкли ставить круглые скобки вокруг аргументов, кроме простых возможностей, таких как MsgBox sString. Рискну сказать, что это трюизм - говорить «когда сомневаешься, окружай». За исключением этого исключительного случая, я считаю, что я применяю это правило в каждом продукте, который я использую.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню