Скрытые возможности VB.NET?

121

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

Итак, каковы некоторые из его скрытых или менее известных особенностей?

Шон Гоф
источник

Ответы:

128

Exception WhenПоложение в значительной степени неизвестно.

Учти это:

Public Sub Login(host as string, user as String, password as string, _
                            Optional bRetry as Boolean = False)
Try
   ssh.Connect(host, user, password)
Catch ex as TimeoutException When Not bRetry
   ''//Try again, but only once.
   Login(host, user, password, True)
Catch ex as TimeoutException
   ''//Log exception
End Try
End Sub
ториальную
источник
9
полезно, если вы хотите поймать конкретное SQLException, скажем -2, что, если я правильно помню, является таймаутом сети: Catch ex as sqlException, где ex.code = -2
Pondidum
Вот Это Да! Я просто прочитал это и сразу же начал использовать, чтобы упростить блок try / catch, который я только что написал на прошлой неделе. Я никогда не знал, что такое существовало.
John M Gant
1
+1 И вот где блог команды NET CLR объясняет, почему фильтры исключений полезны blogs.msdn.com/clrteam/archive/2009/02/05/…
MarkJ 09
5
Это не только скрыто, но и недоступно в C #.
Cheeso
82

изготовленный на заказ Enum s

Одной из реальных скрытых функций VB является completionlistтег XML-документации, который можно использовать для создания собственныхEnum типов с расширенными функциями. Однако эта функция не работает в C #.

Один пример из моего недавнего кода:

'
''' <completionlist cref="RuleTemplates"/>
Public Class Rule
    Private ReadOnly m_Expression As String
    Private ReadOnly m_Options As RegexOptions

    Public Sub New(ByVal expression As String)
        Me.New(expression, RegexOptions.None)
    End Sub

    Public Sub New(ByVal expression As String, ByVal options As RegexOptions)
        m_Expression = expression
        m_options = options
    End Sub

    Public ReadOnly Property Expression() As String
        Get
            Return m_Expression
        End Get
    End Property

    Public ReadOnly Property Options() As RegexOptions
        Get
            Return m_Options
        End Get
    End Property
End Class

Public NotInheritable Class RuleTemplates
    Public Shared ReadOnly Whitespace As New Rule("\s+")
    Public Shared ReadOnly Identifier As New Rule("\w+")
    Public Shared ReadOnly [String] As New Rule("""([^""]|"""")*""")
End Class

Теперь при присвоении значения переменной, объявленной как Rule, IDE предлагает список возможных значений IntelliSense изRuleTemplates .

/РЕДАКТИРОВАТЬ:

Поскольку это функция, основанная на среде IDE, трудно показать, как это выглядит при использовании, но я просто воспользуюсь снимком экрана:

Список дополнений в действии http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png

Фактически, IntelliSense на 100% идентичен тому, что вы получаете при использовании Enum.

Конрад Рудольф
источник
Интересно - не могли бы вы показать пример, как это выглядит, когда вы его потребляете?
Брайан Маккей,
Похоже, кто-то все еще может создать собственное правило, напрямую вызвав конструктор правила? Если да, и если вы хотите это остановить, можете ли вы объявить конструктор как «Друг» в своей библиотеке?
Джоэл Кохорн,
Джоэл, в моем примере кода я намеренно не запрещал этого. Скорее, я предлагаю пользователю несколько общих правил и позволяю создавать собственные, специализированные правила. Конечно, вы можете предотвратить это, пометив конструктор как friendили используя тот же класс, что и перечисление: Ruleвместо RuleTemplate.
Конрад Рудольф
есть ли где-нибудь список использования скрытых полезных атрибутов? этот на первый взгляд кажется невероятным, но я еще не уверен, где бы я его использовал, и мог ли он решить основную проблему в некоторых случаях, когда у меня нет возможности иметь общий, ограниченный перечислениями.
Маслоу
@Maslow: здесь нет атрибута. Это xml-комментарий.
Joel Coehoorn 02
49

Вы заметили оператор сравнения Like?

Dim b As Boolean = "file.txt" Like "*.txt"

Больше из MSDN

Dim testCheck As Boolean

' The following statement returns True (does "F" satisfy "F"?)'
testCheck = "F" Like "F"

' The following statement returns False for Option Compare Binary'
'    and True for Option Compare Text (does "F" satisfy "f"?)'
testCheck = "F" Like "f"

' The following statement returns False (does "F" satisfy "FFF"?)'
testCheck = "F" Like "FFF"

' The following statement returns True (does "aBBBa" have an "a" at the'
'    beginning, an "a" at the end, and any number of characters in '
'    between?)'
testCheck = "aBBBa" Like "a*a"

' The following statement returns True (does "F" occur in the set of'
'    characters from "A" through "Z"?)'
testCheck = "F" Like "[A-Z]"

' The following statement returns False (does "F" NOT occur in the '
'    set of characters from "A" through "Z"?)'
testCheck = "F" Like "[!A-Z]"

' The following statement returns True (does "a2a" begin and end with'
'    an "a" and have any single-digit number in between?)'
testCheck = "a2a" Like "a#a"

' The following statement returns True (does "aM5b" begin with an "a",'
'    followed by any character from the set "L" through "P", followed'
'    by any single-digit number, and end with any character NOT in'
'    the character set "c" through "e"?)'
testCheck = "aM5b" Like "a[L-P]#[!c-e]"

' The following statement returns True (does "BAT123khg" begin with a'
'    "B", followed by any single character, followed by a "T", and end'
'    with zero or more characters of any type?)'
testCheck = "BAT123khg" Like "B?T*"

' The following statement returns False (does "CAT123khg" begin with'
'    a "B", followed by any single character, followed by a "T", and'
'    end with zero or more characters of any type?)'
testCheck = "CAT123khg" Like "B?T*"
Эдуардо Молтени
источник
3
чего ждать? Для меня это в новинку! Хм, это чертовски лучше, чем альтернатива с манипуляциями со строками в VB.NET: D
STW
.. !! Я этого не знал, хотя работал над несколькими проектами vb.net! Интересная особенность ...
Мета-Рыцарь
woooooooooooooooooooooooow! Спасибо! это потрясающе! в ELinq, DLinq тоже работает? что насчет XLinq?
Shimmy Weitzhandler
@dotjoe Хм? В этих шариках нет ничего «ленивого».
Джош Ли
Как это работает, что происходит под капотом? Это синоним библиотек reg ex?
brumScouse
48

Определения типов

VB знает примитивный вид псевдонимов typedefчерез Import:

Imports S = System.String

Dim x As S = "Hello"

Это более полезно при использовании в сочетании с универсальными типами:

Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)
Конрад Рудольф
источник
2
покажите, пожалуйста, пример: слово «Импорт» не распознается в моей среде IDE.
Шимми Вайцхандлер,
5
Importsтак должно быть. ;-) Каким-то образом эта ошибка осталась незамеченной (и собрала 28 голосов) почти целый год.
Конрад Рудольф
Я всегда задавался вопросом, как я могу создать новый «тип» со значениями по умолчанию для универсального! Прохладно!
eidylon 02
3
Импорт, Импорт, Импорт, что угодно! Шиш, ты думаешь, мы читаем эти сообщения, прежде чем проголосовать за них!
MarkJ
Превосходно для использования xunit в тестах Visual Studio, то естьImports Assert = xUnit.Assert
wheelibin
45

Ой! и не забывайте XML-литералы .

Dim contact2 = _
        <contact>
          <name>Patrick Hines</name>
          <%= From p In phoneNumbers2 _
            Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
          %>
        </contact>
Nescio
источник
Вот что я собирался сказать. Фактически, я использовал XML-литералы для целей, для которых это не предназначалось. Я использовал его для создания Javascript ... swortham.blogspot.com/2009/03/vb-2008.html
Стив
9
Помимо прочего, вы можете использовать XML-литералы, чтобы обойти некрасивое экранирование строк, например, когда вы используете строки, которые сами содержат двойные кавычки. Просто поместите строку внутри XML-литерала и вызовите Value, например: <string>This string contains "quotes" and it's OK.</string>.Value (Я нашел это особенно удобным при написании тестов по синтаксическому анализу файлов CSV, где каждое поле было заключено в кавычки. Было бы не интересно избегать всех этих кавычек вручную в моем тестовые строки.)
Райан Ланди
2
@Kyralessa: +1, отличный комментарий. Фактически, это также отличный способ указать многострочные строки (обнимает SQL-запросы и т. Д.).
Heinzi
Встроенный XML - одна из худших возможностей VB.NET, когда-либо задуманных. Необоснованный факт.
Грант Томас
39

Инициализация объекта тоже есть!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
Nescio
источник
1
Не могу поверить, что они использовали фигурные скобки. У нас уже есть оператор With ... они могли бы просто повторно использовать этот синтаксис.
Sam Axe,
2
Я знаю, это сделано только для того, чтобы показать вам, что на дороге нет полицейского ... lol JK
Шимми Вайцхандлер
4
Вот что происходит, когда все авторы компилятора сами в душе программисты C / C ++. Они продолжают переносить синтаксис C на другие языки, потому что не могут представить себе ничего лучше.
RBarryYoung
38

DirectCast

DirectCastэто чудо. На CTypeпервый взгляд, он работает аналогично оператору, поскольку преобразует объект из одного типа в другой. Однако он работает по гораздо более строгому набору правил. CTypeпоэтому фактическое поведение часто бывает непрозрачным, и совершенно не очевидно, какое преобразование выполняется.

DirectCast поддерживает только две различные операции:

  • Распаковка типа значения и
  • повышение уровня иерархии классов.

Любое другое приведение не будет работать (например, попытка распаковать a Integerв a Double) и приведет к ошибке времени компиляции / времени выполнения (в зависимости от ситуации и того, что может быть обнаружено проверкой статического типа). Поэтому я используюDirectCast всякий раз, когда это возможно, так как это лучше всего отражает мое намерение: в зависимости от ситуации я хочу либо распаковать значение известного типа, либо выполнить восходящее преобразование. Конец истории.

Использование CType, с другой стороны, оставляет читателя кода недоумением, что на самом деле задумал программист, потому что он разрешает все виды различных операций, включая вызов определяемого пользователем кода.

Почему это скрытая функция? Команда VB опубликовала руководство 1, которое не рекомендует использовать DirectCast(даже если это на самом деле быстрее!), Чтобы сделать код более единообразным. Я утверждаю, что это плохой совет, который следует отменить: по возможности отдавайте предпочтение оператору DirectCastболее общего характера CType. Это делает код намного понятнее. CType, с другой стороны, должен вызываться только в том случае, если это действительно так, то есть когда должен быть вызван сужающий CTypeоператор (см. перегрузку оператора ).


1) Я не могу найти ссылку на руководство, но я нашел подход Пола Вика (главный разработчик команды VB):

В реальном мире вы вряд ли когда-нибудь заметите разницу, поэтому вы можете использовать более гибкие операторы преобразования, такие как CType, CInt и т. Д.


(РЕДАКТИРОВАТЬ Заком: Узнайте больше здесь: Как мне использовать VB.NET? )

Конрад Рудольф
источник
На самом деле мне немного больше нравится TryCast (). Это не вызовет исключения, просто вернет Nothing, если приведение завершилось неудачно. Если вы ожидаете частого сбоя приведения, это быстрее, чем если TypeOf x Is T ... DirectCast (x, T), и, конечно, быстрее, чем перехват исключения в случае сбоя DirectCast.
Боб Кинг,
6
DirectCast () и TryCast () бесценны при правильном использовании в паре. DirectCast () следует использовать, если предполагается, что приводимый объект всегда будет целевым типом (если это не так, вы получите ошибку, что хорошо, поскольку это непредвиденная ситуация). TryCast () следует использовать, если приводимый объект может быть целевого типа или нескольких целевых типов. Использование одного или другого исключительно приведет либо к дополнительным накладным расходам (если typeof x равен y, тогда directcast (x, y) неэффективен), либо к предотвращению допустимых ошибок (использование TryCast () для случаев, когда объект всегда должен быть целевым типом)
STW
Yoooder: Правильно на 100%. Жаль, что я не упомянул TryCastтогда, потому что в основном мне приходилось ковырять в повсеместном использовании CType.
Конрад Рудольф
@Maslow: конечно, нет, поскольку перечисления являются типами значений и TryCastработают только со ссылочными типами в соответствии с документацией.
Конрад Рудольф
+1: Хех. Должен признаться, я только что прочитал это и подумал: «О да, DirectCast, как я забыл об этом?» И затем я использовал его в моей следующей строке кода (поскольку мне действительно не нравится CType).
RBarryYoung
37

If условный оператор и оператор объединения

Я не знаю, насколько скрытым вы бы это назвали, но функция Iif ([выражение], [значение, если истина], [значение, если ложь]) может считаться.

Это не столько скрыто, сколько устарело ! В VB 9 есть Ifоператор, который намного лучше и работает точно так же, как условный оператор C # и оператор объединения (в зависимости от того, что вы хотите):

Dim x = If(a = b, c, d)

Dim hello As String = Nothing
Dim y = If(hello, "World")

Отредактировано, чтобы показать другой пример:

Это будет работать с If(), но вызовет исключение сIIf()

Dim x = If(b<>0,a/b,0)
Конрад Рудольф
источник
Хорошо, я этого не знала! Я только вчера использовал IIF, поэтому я вернусь к этому блоку кода.
Шон Гоф,
4
Скажите VS 2005 об этом. Не всем из нас удается работать с последними и лучшими.
Сэм Эрвин,
3
@ Шлюха, чушь. Этот метод на 100% безопасен по типу и возвращает объект того же типа, что и его (второй и третий) аргумент. Кроме того, между аргументами должно быть расширяющееся преобразование, иначе произойдет ошибка компиляции из-за несоответствия типов.
Конрад Рудольф
1
Да, его IIf () небезопасен по типу
Pondidum
2
@ Br.Bill Фактически, это полностью эквивалентно:? оператору C и Perl , это не просто упрощенная версия.
Конрад Рудольф
32

Это хороший вариант. Оператор Select Case в VB.Net очень мощный.

Конечно, есть стандарт

Select Case Role
  Case "Admin"
         ''//Do X
  Case "Tester"
         ''//Do Y
  Case "Developer"
         ''//Do Z
  Case Else
       ''//Exception case
End Select

Но это еще не все ...

Вы можете делать диапазоны:

Select Case Amount
 Case Is < 0
    ''//What!!
 Case 0 To 15
   Shipping = 2.0
 Case 16 To 59
    Shipping = 5.87
 Case Is > 59
    Shipping = 12.50
 Case Else
    Shipping = 9.99
 End Select

И даже больше...

Вы можете (хотя это может быть не очень хорошая идея) выполнять логические проверки нескольких переменных:

Select Case True
 Case a = b
    ''//Do X
 Case a = c
    ''//Do Y
 Case b = c
    ''//Do Z
 Case Else
   ''//Exception case
 End Select
ториальную
источник
5
На самом деле вы пропустили пару: a) использование «Select Case True» для проверки более чем одной переменной, b) использование формы «Case A, B, ...» и даже c) применение «:» к in- добавьте в оператор выполнения условие условия (хотя многим это не нравится).
RBarryYoung
6
Пожалуйста, не используйте Select Case True. Просто используйте оператор If.
Райан Ланди,
4
Я считаю, что Select Case True намного легче читать, чем гигантское утверждение ifelse.
dwidel
Проблема Select Case Trueв том, что похоже, что он оценивает каждое из Caseоператоров и запускает код для каждого из них, который является истинным. Но на самом деле он оценивает их один за другим и запускает код только для первого из них, которое является истинным. В этом отношении синтаксис для ( If) намного яснее If...Else If...Else If...Else.
Райан Ланди
31

Одно из основных средств экономии времени, которое я использую постоянно, - это ключевое слово With :

With ReallyLongClassName
    .Property1 = Value1
    .Property2 = Value2
    ...
End With

Я просто не люблю печатать больше, чем нужно!

Jasha87
источник
Но это также создает некоторые скрытые ошибки, особенно когда у вас есть With within With
Варун Махаджан
2
Я даже не знал, что вы можете поместить новый With в существующий With. Это просто неряшливо!
Боб Кинг,
2Боб: Это не небрежно, я бы посоветовал ... это просто языковая конструкция, которую нужно использовать с осторожностью. Для установки множества свойств в последовательных строках это замечательно, но поиск случайного .Foo в сложном фрагменте кода и последующий поиск приведенных выше строк с оператором With - не лучший вариант использования этой функции.
ChrisA
2
Желаю, чтобы в C # это было? Или я спал, и это уже в ответах на скрытые функции C # ...? ;-)
peSHIr
1
@Boo: Вы правы, но все равно досадно, что вы не можете добавить его в список наблюдения.
Meta-Knight,
31

Лучший и простой парсер CSV:

Microsoft.VisualBasic.FileIO.TextFieldParser

Добавив ссылку на Microsoft.VisualBasic, это можно будет использовать на любом другом языке .Net, например C #.

Дальневосточные
источник
5
+1 Странно, как разработчики C # обращаются к FileHelpers, даже не задумываясь об этом. Я уверен, что FileHelpers отличный, но это внешняя зависимость.
MarkJ
@MarkJ Я полагаю, это из-за незнания
Натан Куп,
Я чертовски погуглил, пытаясь найти этот класс, и так и не нашел, спасибо, что поднял его!
pingoo
26
  • Логические операторы AndAlso / OrElse

(РЕДАКТИРОВАТЬ: Узнайте больше здесь: всегда ли мне использовать операторы AndAlso и OrElse? )

Джоэл Кохорн
источник
Я бы вообще не называл это скрытым, если Contact IsNot Nothing AndAlso Contact.ContactId> 0, то сделайте это, если вы будете использовать И вы получите исключение.
Шимми Вайцхандлер,
25

Статические члены в методах.

Например:

Function CleanString(byval input As String) As String
    Static pattern As New RegEx("...")

    return pattern.Replace(input, "")
End Function

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

Другое использование - сохранить экземпляр "random" вокруг:

Function GetNextRandom() As Integer
    Static r As New Random(getSeed())

    Return r.Next()
End Function 

Кроме того, это не то же самое, что просто объявить его как Shared-член класса; элементы, объявленные таким образом, также гарантированно будут потокобезопасными. В этом сценарии это не имеет значения, поскольку выражение никогда не изменится, но есть и другие, где это может измениться.

Джоэл Кохорн
источник
1
Одно из применений этого - сохранение счетчика, который будет увеличиваться каждый раз при вызове метода. Если переменная помечена как статическая, она не будет повторно инициализироваться при каждом вызове метода; он будет инициализирован только при первом вызове и после этого сохранит свое значение.
Райан Ланди,
Это причина, по которой статические члены класса называются "общими" в VB.NET
Энрико Кампидоглио,
Статика - это плохой тон в VB.NET даже больше, чем в классическом VB. По возможности следует избегать статических переменных.
Sam Axe,
6
@Boo - это довольно разительно. В чем ваше оправдание? Я считаю, что статические переменные полезны.
MarkJ
4
Статический, используемый, как в приведенных выше примерах, допускает уникальную форму инкапсуляции: переменные уровня класса, которые имеют область действия на уровне метода. Без него вам пришлось бы создать переменную уровня класса, которая была бы доступна любому члену класса, даже если вы используете ее только в одном методе.
Райан Ланди,
25

В vb эти операторы отличаются:

/это Double
\будет Integerигнорируя остальные

Sub Main()
    Dim x = 9 / 5  
    Dim y = 9 \ 5  
    Console.WriteLine("item x of '{0}' equals to {1}", x.GetType.FullName, x)
    Console.WriteLine("item y of '{0}' equals to {1}", y.GetType.FullName, y)

    'Results:
    'item x of 'System.Double' equals to 1.8
    'item y of 'System.Int32' equals to 1
End Sub
Шимми
источник
1
Я усвоил это на собственном горьком опыте, когда пытался найти иголку в миллионе строк кода. регулярное и целочисленное деление. хороший совет!
Джейсон Ирвин,
23

Мне очень нравится пространство имен «My», которое было введено в Visual Basic 2005. My - это ярлык для нескольких групп информации и функций. Он обеспечивает быстрый и интуитивно понятный доступ к следующим типам информации:

  • My.Computer : доступ к информации, связанной с компьютером, такой как файловая система, сеть, устройства, системная информация и т. Д. Он обеспечивает доступ к ряду очень важных ресурсов, включая My.Computer.Network, My.Computer.FileSystem и My. .Computer.Printers.
  • My.Application : доступ к информации, относящейся к конкретному приложению, такой как имя, версия, текущий каталог и т. Д.
  • My.User : доступ к информации, относящейся к текущему аутентифицированному пользователю.
  • My.Resources : доступ к ресурсам, используемым приложением, находящимся в файлах ресурсов строго типизированным способом.
  • My.Settings : доступ к параметрам конфигурации приложения строго типизированным способом.
splattne
источник
Это просто здорово, и каждый парень, работающий с vb.net, должен знать что-то в моем пространстве имен, это так полезно.
доктор evil
Мой. * FTW :).
доктор зло
3
Это вроде как полезно, но я ненавижу тупое имя. Напоминает мне об этом secretgeek.net/refactvb.asp
MarkJ 09
23

Пользовательские события

Обработка событий редко бывает полезной, но ее можно сильно настроить:

Public Class ApplePie
    Private ReadOnly m_BakedEvent As New List(Of EventHandler)()

    Custom Event Baked As EventHandler
        AddHandler(ByVal value As EventHandler)
            Console.WriteLine("Adding a new subscriber: {0}", value.Method)
            m_BakedEvent.Add(value)
        End AddHandler

        RemoveHandler(ByVal value As EventHandler)
            Console.WriteLine("Removing subscriber: {0}", value.Method)
            m_BakedEvent.Remove(value)
        End RemoveHandler

        RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
            Console.WriteLine("{0} is raising an event.", sender)
            For Each ev In m_BakedEvent
                ev.Invoke(sender, e)
            Next
        End RaiseEvent
    End Event

    Public Sub Bake()
        ''// 1. Add ingredients
        ''// 2. Stir
        ''// 3. Put into oven (heated, not pre-heated!)
        ''// 4. Bake
        RaiseEvent Baked(Me, EventArgs.Empty)
        ''// 5. Digest
    End Sub
End Class

Затем это можно проверить следующим образом:

Module Module1
    Public Sub Foo(ByVal sender As Object, ByVal e As EventArgs)
        Console.WriteLine("Hmm, freshly baked apple pie.")
    End Sub

    Sub Main()
        Dim pie As New ApplePie()
        AddHandler pie.Baked, AddressOf Foo
        pie.Bake()
        RemoveHandler pie.Baked, AddressOf Foo
    End Sub
End Module
Конрад Рудольф
источник
кажется крутым, но если мне это когда-нибудь понадобится, думаю, я что-то сделал не так ;-). Это просто кажется противоречащим принципу KISS.
chrissie1
4
Это действительно очень полезно, когда вы хотите убедиться, что каждый приемник получает событие, даже если один или несколько выдают исключение.
Джонатан Аллен,
Другое значение (я только что прочитал его на сайте MSDN): если ваш класс генерирует много событий, вы можете заставить его использовать хэш-таблицу / словарь в качестве контейнера, а не объявлять поле для каждого события. msdn.microsoft.com/en-us/library/8627sbea(VS.71).aspx
ториальный
Прохладно. Я думал, что это одна из функций, которые отличают C # и VB.NET (как в одном, но в другом нет синтаксиса для него). Приятно хотя бы знать, что я был неправ в этом отношении.
peSHIr
21

Я только что нашел статью, в которой говорится о "!" оператор, также известный как «оператор поиска по словарю». Вот отрывок из статьи по адресу: http://panopticoncentral.net/articles/902.aspx

Техническое название! Оператор - это «оператор поиска по словарю». Словарь - это любой тип коллекции, который индексируется ключом, а не числом, точно так же, как записи в английском словаре индексируются по слову, определение которого вы хотите. Наиболее распространенным примером типа словаря является System.Collections.Hashtable, которая позволяет добавлять пары (ключ, значение) в хеш-таблицу, а затем извлекать значения с помощью ключей. Например, следующий код добавляет три записи в хеш-таблицу и ищет одну из них с помощью ключа «Свинина».

Dim Table As Hashtable = New Hashtable
Table("Orange") = "A fruit"
Table("Broccoli") = "A vegetable"
Table("Pork") = "A meat" 
Console.WriteLine(Table("Pork"))

! Оператор может использоваться для поиска значений из любого типа словаря, который индексирует свои значения с помощью строк. Идентификатор после! используется как ключ в операции поиска. Таким образом, вместо этого можно было написать приведенный выше код:

Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)

Второй пример полностью эквивалентен первому, но выглядит намного лучше, по крайней мере, на мой взгляд. Я считаю, что есть много мест, где! могут быть использованы, особенно когда речь идет о XML и Интернете, где существует множество коллекций, индексируемых по строкам. Одно досадное ограничение заключается в том, что после! по-прежнему должен быть действительным идентификатором, поэтому, если строка, которую вы хотите использовать в качестве ключа, содержит недопустимый символ идентификатора, вы не можете использовать! оператор. (Вы не можете, например, сказать «Таблица! AB $ CD = 5», потому что $ недопустимы в идентификаторах.) В VB6 и ранее вы могли использовать скобки для исключения недопустимых идентификаторов (например, «Таблица! [AB $ CD] "), но когда мы начали использовать квадратные скобки для экранирования ключевых слов, мы потеряли возможность это сделать. В большинстве случаев,

Чтобы получить действительно технический характер, x! Y работает, если x имеет свойство по умолчанию, которое принимает String или Object в качестве параметра. В этом случае x! Y заменяется на x.DefaultProperty ("y"). Интересно отметить, что в лексической грамматике языка есть специальное правило, чтобы все это работало. ! Символ также используется в качестве символа типа в языке, а символы типа съедаются перед операторами. Таким образом, без специального правила x! Y будет сканироваться как «x! Y» вместо «x! Y». К счастью, поскольку в языке нет места, где действительны два идентификатора подряд, мы просто ввели правило, что если следующий символ после! является началом идентификатора, мы считаем! быть оператором, а не типом.

ториальную
источник
11
Это одна из тех функций, которые я использовал, но намеренно забыл. Это экономит несколько нажатий клавиш, но портит подсветку и читаемость моего кода. снова забываю, верно .... СЕЙЧАС
STW
3
Интересно, но бесполезно. Над этим ли работает команда VB вместо того, чтобы добавлять недостающие функции, такие как ключевое слово yield? : P
Мета-Рыцарь
5
Эта функция перенесена для обратной совместимости из VB3 (AFAIK)
Эдуардо Молтени
1
Есть ли у тех классов, которые реализуют ключевой индекс, общий интерфейс, от которого они наследуются? как IKeyed, так же как контейнеры с целочисленным индексом реализуют IENumberable?
Маслоу
2
Эта функция также работает с DataRows (т.е. dr! ID), что ОЧЕНЬ удобно в LINQ to DataSets.
Пол
19

Это встроено, и это явное преимущество перед C #. Возможность реализовать метод интерфейса без использования того же имени.

Такие как:

Public Sub GetISCSIAdmInfo(ByRef xDoc As System.Xml.XmlDocument) Implements IUnix.GetISCSIInfo

End Sub
ториальную
источник
Я почти уверен, что вы можете сделать что-то подобное на C #. В VB.NET это просто принудительно, а в C # - необязательно?
Джеспер Блад Дженсен,
5
Вы также можете сделать sub private, что является отличным способом скрыть такие вещи, как вызовы неуниверсальных устаревших версий интерфейсов.
Крейг Гидни,
3
Это может быть хорошей идеей. Классическим примером может быть метод Public Close, который также действует как реализация Dispose для IDisposable.
MarkJ
1
Это также очень полезно, если вам случится реализовать два интерфейса с общим именем метода.
Эрик Николсон
Я видел это и всегда жалел, что не видел. Не должно быть допущено.
FastAl
17

Форсирование ByVal

В VB, если вы заключите свои аргументы в дополнительный набор круглых скобок, вы можете переопределить объявление метода ByRef и превратить его в ByVal. Например, следующий код производит 4, 5, 5 вместо 4,5,6

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim R = 4
    Trace.WriteLine(R)
    Test(R)
    Trace.WriteLine(R)
    Test((R))
    Trace.WriteLine(R)
End Sub
Private Sub Test(ByRef i As Integer)
    i += 1
End Sub

См. Аргумент, не изменяемый вызовом процедуры - базовая переменная

Крис Хаас
источник
6
О, боже мой ... это замечательная особенность, хотя я не думаю, что узнаю, что она делает, если я прочту ее в чужом коде. Если вам нужно прокомментировать это, чтобы знать, что он делает, вы могли бы вместо этого передать переменную throw away.
mattmc3
7
На самом деле это побочный эффект использования скобок - скобки создают временное значение того, что внутри, даже если только один элемент. Этот эффект УБИЛ МЕНЯ в vb6 - Подвызовы не принимали паренсы, но я, пришедший из C, инстинктивно вставлял их. 6.0 взорвался на нескольких параметрах, но для одного подпараметра он с радостью передал временное значение и ОТКАЗАЛСЯ, чтобы соблюдать мои 'ByRef. Происходило примерно каждые 3 года, примерно за время, которое мне потребовалось, чтобы забыть последний инцидент.
FastAl
16

Передача параметров по имени и их переупорядочивание

Sub MyFunc(Optional msg as String= "", Optional displayOrder As integer = 0)

    'Do stuff

End function

Использование:

Module Module1

    Sub Main()

        MyFunc() 'No params specified

    End Sub

End Module

Также может вызываться с использованием спецификации параметра ": =" в любом порядке:

MyFunc(displayOrder:=10, msg:="mystring")
49%
источник
Вау, это супер круто! Я видел это при использовании веб-служб и т. Д., Но я не знал, что вы можете сделать это каким-либо обычным способом.
RichC,
2
Определенно очень удобный инструмент, когда вы сталкиваетесь с методом, который принимает слишком много аргументов. Я пытаюсь назвать каждый параметр и помещать имя: = значение в отдельной строке. Он намного более интуитивно понятен и понятен для методов, которые принимают> 5 (мое практическое правило) параметров.
STW
Особенно полезно для автоматизации делопроизводства, где вам приходится иметь дело с методами с десятками необязательных аргументов.
MarkJ
1
Что еще круто, так это то, что вы можете смешивать эти два параметра: сначала укажите необходимые параметры по порядку, а затем переключитесь на именованные параметры для дополнительных аргументов!
RBarryYoung
15

Оператор Using появился в VB 8 впервые, в C # он был с самого начала. Он вызывает автоматическое удаление за вас.

Например

Using lockThis as New MyLocker(objToLock)

End Using
ториальную
источник
23
Стоит отметить (только потому, что я как минимум дважды забыл), что вы можете использовать один оператор Using для обертывания нескольких объектов Disposable. Синтаксис: «Использование objA как нового объекта, objB как нового объекта…» Это намного чище, чем вложение нескольких операторов Using.
STW
Определенно один из моих любимых.
Sam Axe,
14

Псевдонимы импорта также в значительной степени неизвестны:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form
ториальную
источник
1
Думаю, у нас была такая же идея.
chrissie1
3
@Boo - вот простой пример, когда псевдонимы импорта не являются злом. stackoverflow.com/questions/92869/…
учебное пособие
Хорошо, есть очевидная возможность для злоупотреблений, но независимо от тирады @ torial, это отличная функция. Каждый раз, когда я включаю System.Text.RegularExpressions, я рискую столкнуться с конфликтом имен с классом "Group", поскольку это общее имя класса. Псевдоним позволяет избежать необходимости полностью определять неоднозначные классы, что значительно экономит время и фактически улучшает читаемость при правильном использовании. Функция отличная, но ваш конкретный пример действительно вызывает насмешки - извините.
mattmc3
14

Рассмотрим следующее объявление события

Public Event SomethingHappened As EventHandler

В C # вы можете проверить подписчиков на события, используя следующий синтаксис:

if(SomethingHappened != null)
{
  ...
}

Однако компилятор VB.NET не поддерживает это. Фактически он создает скрытое поле закрытого члена, которое не отображается в IntelliSense:

If Not SomethingHappenedEvent Is Nothing OrElse SomethingHappenedEvent.GetInvocationList.Length = 0 Then
...
End If

Больше информации:

http://jelle.druyts.net/2003/05/09/BehindTheScenesOfEventsInVBNET.aspx http://blogs.msdn.com/vbteam/archive/2009/09/25/testing-events-for-nothing-null-doug -rothaus.aspx

техноболтовня
источник
Зачем вам это нужно? Я не могу представить себе вариант использования, когда вам нужно знать количество подписчиков на событие в VB.
Конрад Рудольф
В определенных обстоятельствах C # выдает исключение, если вы вызываете событие и нет обработчиков. VB.Net не будет. Отсюда и необходимость проверки.
Joel Coehoorn
2
Я использовал это для события бизнес-объекта, которое вызывало у подписчиков сообщения об ошибках проверки. Я хотел проверить, обрабатывается ли событие, чтобы я знал, что были получены ошибки проверки. В противном случае бизнес-объект генерировал исключение.
Техно-болтовня
2
Еще одно удобное использование этого закрытого члена - получение списка вызовов события. Я использовал его в нескольких случаях, чтобы запускать событие асинхронно для всех вызывающих (предотвращает изменение события прослушивателем A до его получения прослушивателем B; также это предотвращает задержку доставки прослушивателем A прослушивателю B). Я много использовал это в пользовательских сценариях синхронизации данных, а также в API.
STW
14

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

например

Class CodeException
Public [Error] as String
''...
End Class

''later
Dim e as new CodeException
e.Error = "Invalid Syntax"

например, пример из комментариев (@Pondidum):

Class Timer
Public Sub Start()
''...
End Sub

Public Sub [Stop]()
''...
End Sub
ториальную
источник
Я думаю, что этот пример был бы лучше, если бы вы не использовали «If» в качестве ключевого слова примера.
Шон Гоф,
4
timer.Start и timer.Stop приходят на ум в качестве примеров хорошего использования этого
Pondidum
5
+1 за указание на это с отказом от ответственности. Есть несколько классов фреймворка, которые требуют правильного решения, например [Assembly]
STW
5
[Enum] - еще один хороший пример случая, когда вам нужны скобки, чтобы использовать класс вместо ключевого слова.
Райан Ланди
13

Есть несколько ответов о XML-литералах, но не об этом конкретном случае:

Вы можете использовать XML-литералы, чтобы заключить строковые литералы, которые в противном случае нужно было бы экранировать. Например, строковые литералы, содержащие двойные кавычки.

Вместо этого:

Dim myString = _
    "This string contains ""quotes"" and they're ugly."

Ты можешь сделать это:

Dim myString = _
    <string>This string contains "quotes" and they're nice.</string>.Value

Это особенно полезно, если вы тестируете литерал для синтаксического анализа CSV:

Dim csvTestYuck = _
    """Smith"", ""Bob"", ""123 Anywhere St"", ""Los Angeles"", ""CA"""

Dim csvTestMuchBetter = _
    <string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value

(Вам, конечно, не обязательно использовать <string>тег; вы можете использовать любой тег, который вам нравится.)

Райан Ланди
источник
3
<q>был бы хорошим тегом, похожим на использование в Perl / Ruby. В любом случае, это неплохая идиома. ЛАЙК!
Конрад Рудольф
Какая гениальная идея. Спасибо
Джереми
12

DateTime можно инициализировать, заключив дату в #

Dim independanceDay As DateTime = #7/4/1776#

Вы также можете использовать вывод типа вместе с этим синтаксисом

Dim independanceDay = #7/4/1776#

Это намного приятнее, чем использовать конструктор

Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
danlash
источник
6
Нет, если у вас есть Option Strict On
danlash
12

У вас может быть 2 строки кода всего в одной строке. следовательно:

Dim x As New Something : x.CallAMethod
Parsa
источник
эй ... я думал, что это возможно только с классом и наследованием
Джейсон
Не забывайтеCall (New Something).CallAMethod()
Джонатан Аллен
Это холдевер от MS-Basic для Apple] [! В моем магазине меня бы так же высмеяли за использование Gotos: - /
FastAl
В большинстве случаев этого следует избегать, но я предпочитаю использовать это в случаях, когда строки действительно короткие, например, случай 4: x = 22
dwidel
11

Дополнительные параметры

Варианты намного проще, чем создавать новые перегрузки, такие как:

Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
   Console.Writeline(msg)
   ''//do stuff
End Function
др. злой
источник
1
Я не знал, что C # их получит. Они хороши, но вы должны быть осторожны, чтобы использовать их только там, где вы уверены, что код не будет использоваться C #, поскольку он их не поддерживает. FxCop / Code Analysis скажет вам вместо этого перегрузить метод.
STW
... Я только что нашел отличное применение необязательным параметрам, сохранив при этом их вне производственного кода. Я написал об этом небольшой пост на своем сайте: yoooder.com/wordpress/?p=62
STW
2
Ах, я так сильно это презираю ... Но полезно для автоматизации
делопроизводства
9

Заглавный регистр в VB.Net можно получить с помощью старого VB6 fxn:

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
ториальную
источник
1
это также в классе textinfo. Не уверен, в каком пространстве имён. вероятно, system.text
Шон
Лучше быть нейтральным к языку .net и использовать класс Globalization TextInfo для преобразования ToTitleCase. Если ваш код когда-либо потребуется преобразовать в C #, у вас будет много мелких неприятностей, требующих Microsoft.VisualBasic
Джереми
9

Свойства с параметрами

Я занимался программированием на C # и обнаружил функцию, которая отсутствовала в VB.Net, но не упоминалась здесь.

Пример того, как это сделать (а также ограничение C #), можно увидеть по адресу: Использование типичных свойств get set в C # ... с параметрами

Я взял код из этого ответа:

Private Shared m_Dictionary As IDictionary(Of String, Object) = _
             New Dictionary(Of String, Object)

Public Shared Property DictionaryElement(ByVal Key As String) As Object
    Get
        If m_Dictionary.ContainsKey(Key) Then
            Return m_Dictionary(Key)
        Else
            Return [String].Empty
        End If
    End Get
    Set(ByVal value As Object)
        If m_Dictionary.ContainsKey(Key) Then
            m_Dictionary(Key) = value
        Else
            m_Dictionary.Add(Key, value)
        End If

    End Set
End Property
урок
источник
Это интересно, но я не совсем уверен, где это может быть полезно. myObj.Something ("abc") больше похож на доступ к функции, чем к свойству. Не уверен, что это тебе выгодно.
mattmc3
Ненавижу двусмысленность. Что должно быть. Метод или свойство. Некоторые инструменты рефакторинга предлагают создавать и то, и другое в определенных ситуациях, похоже, они даже не знают ...
brumScouse