Убедитесь, что ParamArray содержит правильные типы параметров.

Я пытаюсь использовать ParamArray для передачи различных параметров одной и той же функции для имитации перегрузки функции.

  • Один единственный String
  • Один Workbook объект, один String, а также Integer

Таким образом, пользователь может передавать разные аргументы одной и той же функции:

Function func(ParamArray params() As Variant)

blah = func("This is a string")

blah = func(wbSource, "SheetName", iRow)

Есть ли способ проверить типы аргументов? Мне нужно убедиться, что params() содержит правильные типы аргументов (один workbook, один string и один integer).

Конечно, я могу жестко кодировать с кучей If-Else, но что, если в будущем аргументов станет больше? Я думаю об использовании TypeName() для сброса типов в массив String, а затем провести сравнение. Но это все еще кажется громоздким. Есть ли лучший способ добиться этого?

Кстати, я не думаю, что Optional — хорошая идея, потому что кто знает, сколько будет аргументов?


person Nicholas Humphrey    schedule 14.06.2018    source источник
comment
Посмотрите, что может сделать для вас функция VarType — гораздо более надежная, чем TypeName, хотя и не менее громоздкая.   -  person Mathieu Guindon    schedule 14.06.2018
comment
@MathieuGuindon Спасибо! Тем не менее, может быть, сама конструкция испорчена?   -  person Nicholas Humphrey    schedule 14.06.2018
comment
Вот что утверждает мой черновик ответа, да   -  person Mathieu Guindon    schedule 14.06.2018


Ответы (2)


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

IMO, это ужасная идея: вы теряете проверку количества аргументов во время компиляции, теряете intellisense на сайтах вызовов, сообщающих вам, каковы ожидаемые параметры и типы.

C# начинался с перегрузки методов и развивался для поддержки необязательных параметров. Теперь, когда поддерживаются необязательные параметры, перегрузка методов в C# является просто альтернативой необязательным параметрам и наоборот.

VBA поддерживает необязательные параметры, но не перегрузку методов. Большое дело: вы можете использовать необязательные параметры и добиться того же, что и альтернатива перегрузки методов в C#.

ParamArray не вариант.

Ответ на вопрос "есть ли способ проверить типы аргументов" - ДА! Пусть компилятор сделает свою работу!

Я не думаю, что Optional — это хорошая идея, потому что кто знает, сколько аргументов будет?

Если вы этого не сделаете, никто не знает! Метод со слишком большим количеством аргументов часто является запахом кода: не отвечает ли метод за слишком много вещей? Точно ли название передает все, что он делает? Трудно сказать, что вы предоставили, но я бы сказал, что если вы пишете метод и не знаете, сколько аргументов ему понадобится, как вы узнаете, что этот метод должен делать?

person Mathieu Guindon    schedule 14.06.2018
comment
Спасибо за ответ. Имеет смысл, кажется, мне кажется, что я использую расширенную функцию, которую очень легко реализовать на C++, но как-то странно в VBA. Так как пока у меня только два кейса, я разобью их на две функции. - person Nicholas Humphrey; 14.06.2018
comment
@NicholasHumprey, в зависимости от того, что конкретно происходит, более продвинутый дизайн ООП может реализовать шаблон стратегии и получить некоторый параметр IAction (независимо), за предоставление которого может отвечать сайт вызова - IDK, дизайн довольно расплывчатый здесь. Просто знайте, что почти все, что вы можете придумать с точки зрения ООП, достижимо в VBA - до тех пор, пока вы не пытаетесь задействовать делегатов и другие экзотические конструкции. - person Mathieu Guindon; 14.06.2018
comment
Спасибо Матье! Не могли бы вы немного подробнее рассказать о Стратегическом шаблоне? Из того, что я прочитал в Интернете, это включает в себя создание интерфейса, скажем, IAction и Implements IAction для реальных действий. Таким образом, пользователи должны предоставить эти объекты, и будут сделаны соответствующие вызовы функций. Но, как вы сказали, это очень расплывчато. У меня был некоторый опыт работы с C++, поэтому я знаю полиморфизм, но очень смутно. Это то же самое, о чем вы говорите? Спасибо! - person Nicholas Humphrey; 15.06.2018
comment
Да, полиморфизм именно он =) - person Mathieu Guindon; 15.06.2018
comment
Спасибо, я посмотрю, подойдет ли он. На данный момент, TBH, у меня есть только два разных случая, думаю, это слишком много, - person Nicholas Humphrey; 15.06.2018

Я думаю, что вы ответили на свой вопрос в вопросе. Вам нужно использовать массив для хранения того, какие типы допустимы для вас, и проверить, находится ли тип внутри. Вы можете сделать это, используя TypeName() или VarType(), как объяснил Матье Гиндон в разделе комментариев. Пример:

Dim IntVar, StrVar, DateVar, MyCheck
' Initialize variables.
IntVar = 459: StrVar = "Hello World": DateVar = #2/12/69# 
MyCheck = VarType(IntVar)    ' Returns 2.
MyCheck = VarType(DateVar)    ' Returns 7.
MyCheck = VarType(StrVar)    ' Returns 8.
person Lajos Arpad    schedule 14.06.2018
comment
Спасибо, я думаю, это один из двух способов (а optional — другой) реализовать это. Очень громоздко, я откажусь от дизайна. - person Nicholas Humphrey; 14.06.2018