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

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

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

64 ответа

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

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

Одна из реальных скрытых особенностей 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

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

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

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

http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png

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

Вы заметили оператор сравнения 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*"

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

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

Imports S = System.String

Dim x As S = "Hello"

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

Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)

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

Dim contact2 = _
        <contact>
          <name>Patrick Hines</name>
          <%= From p In phoneNumbers2 _
            Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
          %>
        </contact>

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

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}

DirectCast

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

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

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

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

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

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


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

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


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

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)

Это хороший. Оператор 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

Лучший и простой анализатор CSV:

Microsoft.VisualBasic.FileIO.TextFieldParser

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

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

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

Мне просто не нравится печатать больше, чем нужно!

  • AndAlso/OrElse логические операторы

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

В 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

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

Например:

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 член класса; элементы, объявленные таким образом, также гарантированно поточно-ориентированы. Это не имеет значения в этом сценарии, так как выражение никогда не изменится, но есть другие, где оно может измениться.

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

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

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

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

  • My.Computer: доступ к информации, относящейся к компьютеру, такой как файловая система, сеть, устройства, системная информация и т. Д. Он обеспечивает доступ к ряду очень важных ресурсов, включая My.Computer.Network, My.Computer.FileSystem и My.Computer.Printers.
  • My.Application: доступ к информации, связанной с конкретным приложением, такой как имя, версия, текущий каталог и т. Д.
  • My.User: доступ к информации, связанной с текущим аутентифицированным пользователем.
  • My.Resources: Доступ к ресурсам, используемым приложением, находящимся в файлах ресурсов строго типизированным способом.
  • My.Settings: Доступ к настройкам конфигурации приложения строго типизированным способом.

Я только что нашел статью о "!" оператор, также известный как "оператор поиска в словаре". Вот выдержка из статьи по адресу: 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 и Интернете, где есть только тонны коллекций, которые индексируются по строке. Одно досадное ограничение - это то, что следует за! все еще должен быть допустимым идентификатором, поэтому, если в строке, которую вы хотите использовать в качестве ключа, есть какой-то недопустимый символ идентификатора, вы не можете использовать! оператор. (Например, вы не можете сказать "Table!AB$CD = 5", потому что $ недопустимо в идентификаторах.) В VB6 и ранее вы могли использовать скобки для экранирования недопустимых идентификаторов (то есть "Table![AB$"). CD]"), но когда мы начали использовать скобки для экранирования ключевых слов, мы потеряли способность делать это. Однако в большинстве случаев это не слишком большое ограничение.

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

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

Такие как:

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

End Sub

Форсирование 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

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

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

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")

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

Например

Using lockThis as New MyLocker(objToLock)

End Using

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

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form

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

например

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

Рассмотрим следующую декларацию события

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

Есть несколько ответов о 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> тег, конечно; Вы можете использовать любой тег, который вам нравится.)

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

Dim x As New Something : x.CallAMethod

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

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

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

Dim independanceDay = #7/4/1776#

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

Dim independanceDay as DateTime = New DateTime(1776, 7, 4)

Необязательные параметры

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

Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
   Console.Writeline(msg)
   ''//do stuff
End Function

Составлять / группировать несколько, используя операторы вместе:

Dim sql As String = "StoredProcedureName"
Using cn As SqlConnection = getOpenConnection(), _
      cmd As New SqlCommand(sql, cn), _
      rdr As SqlDataReader = cmd.ExecuteReader()

    While rdr.Read()

        ''// Do Something

    End While

End Using

Если честно, вы можете сделать это и в C#. Но многие люди не знают об этом ни на одном языке.

Название Case в VB.Net может быть достигнуто с помощью старого VB6 fxn:

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
Другие вопросы по тегам