Есть ли в VB.NET эквивалент выходных параметров C #?

95

Есть ли в VB.NET прямой эквивалент outпараметров функции C # , где переменная, передаваемая в функцию, не требует инициализации?

cspolton
источник

Ответы:

98

Нет, outв VB нет эквивалента ключевому слову.

Однако VB автоматически инициализирует все локальные переменные в методе, поэтому вы можете использовать их ByRefбез необходимости сначала явно инициализировать переменную.

Пример:

Sub Main()
  Dim y As Integer
  Test(y)
End Sub

Sub Test(ByRef x As Integer)
  x = 42
End Sub

(Если вы исследуете код в структуре (например, Double.TryParse ), вы можете увидеть <OutAttribute>добавленные параметры, но это имеет значение только тогда, когда вызов маршалируется для COM-взаимодействия или вызова платформы.)

Гуффа
источник
2
@Spolto: если вы переводите VBScript в VB, вы должны убедиться, что включены явный и строгий режимы. Это даст вам больше сообщений об ошибках, но большинство из них будет указывать на источник проблем (например, переменная, объявленная без типа), а не на вторичные проблемы (например, переменная, объявленная без типа, становится переменной Object, поэтому ее нельзя использовать в качестве ByRef x As Integerпараметра).
Guffa
4
@Guffa: Я не знаю, относится ли это к версии, но я тоже получаю предупреждения компилятора при передаче неинициализированных переменных ссылочного типа в качестве ByRefпараметров. (Этого не происходит с параметрами типа значения.)
Дэн Тао
4
@Dan Tao, Spolto: Кажется, в этом разница, я также получаю предупреждение со ссылочными типами. Невозможность указать параметры - это ограничение языка, и вам просто нужно инициализировать переменные, чтобы избавиться от предупреждений. Даже назначение Nothingим избавит от предупреждения, хотя и не изменит результат.
Guffa
1
@Guffa: Да, я пока Nothingих назначал . Это просто отнимает много времени, так как мне приходится делать это сотни раз на большом устаревшем веб-сайте. Спасибо за расследование.
cspolton
3
@MarkHurd: Тогда отрицательный голос несправедлив, потому что я уже говорил, что этот Outатрибут не эквивалентен outключевому слову C # .
Guffa
32

Нет, не существует эквивалентная конструкция , которая позволяет не инициализирован переменной быть передан методу без предупреждения, но, как уже упоминалось в моем вопросе и ответе указав <Out()>атрибут на ByRefопределение параметров, хотя VB игнорирует его, это лечится C # в качестве outпараметра.

Итак, я бы предварительно инициализировал ссылочные переменные Nothing и указал их <Out()> ByRefдля обозначения намерения (это будет работать, если пользователи C # когда-либо будут обращаться к вашим методам).

Если вы чувствуете, что знаете, когда вы намереваетесь получить доступ к значениям по умолчанию Nothingв неназначенных ссылочных переменных, вы можете установить для параметра «Конфигурация предупреждения» «Использование переменной до назначения» значение «Нет» на уровне проекта (Свойства проекта> Компилировать, и вы, вероятно вы хотите установить для конфигурации значение «Все конфигурации» перед изменением этого параметра) или, в VS2015 (VB.NET 14), вы можете использовать #Disable Warning BC42030.

Марк Херд
источник
3
Это важно. У меня был подкласс VB от MembershipProvider, а затем подкласс C # подкласса VB. Код C # не распознавал тот факт, что абстрактные методы в MembershipProvider уже были реализованы, пока я не применил атрибут в классе VB для параметров, которые были указаны как отсутствующие в базовом классе MembershipProvider.
Ричард Коллетт
@RichardCollette Вероятно, стоит ответить на мой связанный вопрос!
Марк Херд
9

Версия C #

  void TestFunc(int x, ref int y, out int z) {
  x++;  
  y++;
  z = 5;
}

Версия Vb.net

    Sub TestFunc(ByVal x As Integer, ByRef y As Integer, ByRef z As Integer)
  x += 1
  y += 1 
  z = 5 
End Sub

Нашел ответ здесь

Обновить

Как указано в комментарии, не забудьте инициализировать свой параметр, который будет использоваться в выходном слоте.

Дэвид
источник
В целом согласен, что ByRef - это наиболее близкая вещь к ауте . Однако ByRef все равно выдаст предупреждение, если вы передадите переменную неинициализированной, как задается в вопросе.
Ричард
Мое отрицательное голосование было высказано довольно давно: веб-сайт, на который вы ссылаетесь, носит очень общий характер; в нем не перечислены конкретные проблемы, различия и технические детали. Также ваш ответ все еще не отвечает на вопрос.
Марк Херд
1

У меня была проблема в VB.NET: я вызвал функцию «по ссылке», которая вернула массив.

Несмотря на то, что компилятор пометил это как предупреждение, все в порядке. Исправление очень простое и, вероятно, хорошая практика программирования.

Я изменился

Dim m_arr_values() as Integer

fnRetArray(m_arr_values)

к

' Even though 'Nothing' is the default value, setting it
' stops the compiler complaining.
Dim m_arr_values() as Integer = Nothing

fnRetArray(m_arr_values)

Это также помогает при кодировании, если имена переменных описательны ...

Sub fnCreatePalette(ByRef arr_in_pal() As color, ByRef arr_out_pal() as uinteger)
    ...
End Sub
TheWhitde
источник
3
Венгерская нотация противоречит руководству по проектированию .NET Framework.
Gqqnbig
0

Вы можете использовать метод передачи по ссылке в VB.NET.

Вам нужен механизм параметров Out в C #, потому что он не позволяет использовать никакую переменную без ее инициализации.

VB.NET не требует специального ключевого слова, так как он делает это автоматически.

Просто используйте ByRef.

Джош
источник
3
Это не отвечает на вопрос, и это неправильно по отношению к C #.
cspolton
Byref позволяет не выполнять инициализацию и позволяет изменять значение параметров. Но, в отличие от параметра вывода C #, он ПОЗВОЛЯЕТ вам инициализировать параметр значением и использовать его в функции, тогда как в C # ключевое слово out заставляет вас использовать его ТОЛЬКО как параметр вывода, а НЕ как ввод для функция. Кроме того, если вы не измените или не установите значение для этого параметра в своей функции, компилятор не распознает это как ошибку, в отличие от C #, где будет выдана ошибка компиляции.
пашуте
0

VB имеет атрибут, который должен быть таким же, как C #, но сегодня вы все равно получаете предупреждение, даже если вы его используете. Подробности о том, как это исправить, можно найти в разделе vblang на гитхабе. https://github.com/dotnet/vblang/issues/67 .

Пол Коэн
источник
-5

Используйте ключевое слово ByRef перед переменной.

deostroll
источник
4
ByRefэквивалентен refпараметрам в C #, которые необходимо инициализировать перед передачей в функцию.
cspolton 05