Скрытые возможности 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
изготовленный на заказ 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
,
Вы заметили оператор сравнения 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