Я довольно много узнал, просматривая скрытые возможности C # и был удивлен, когда не смог найти что-то подобное для VB.NET.
Итак, каковы некоторые из его скрытых или менее известных особенностей?
Я довольно много узнал, просматривая скрытые возможности C # и был удивлен, когда не смог найти что-то подобное для VB.NET.
Итак, каковы некоторые из его скрытых или менее известных особенностей?
Ответы:
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
.
friend
или используя тот же класс, что и перечисление: Rule
вместо RuleTemplate
.
Вы заметили оператор сравнения 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)
Imports
так должно быть. ;-) Каким-то образом эта ошибка осталась незамеченной (и собрала 28 голосов) почти целый год.
Imports Assert = xUnit.Assert
Ой! и не забывайте XML-литералы .
Dim contact2 = _
<contact>
<name>Patrick Hines</name>
<%= From p In phoneNumbers2 _
Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
%>
</contact>
<string>This string contains "quotes" and it's OK.</string>.Value
(Я нашел это особенно удобным при написании тестов по синтаксическому анализу файлов CSV, где каждое поле было заключено в кавычки. Было бы не интересно избегать всех этих кавычек вручную в моем тестовые строки.)
Инициализация объекта тоже есть!
Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
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
тогда, потому что в основном мне приходилось ковырять в повсеместном использовании CType
.
TryCast
работают только со ссылочными типами в соответствии с документацией.
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)
:?
оператору C и Perl , это не просто упрощенная версия.
Это хороший вариант. Оператор 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
Select Case True
в том, что похоже, что он оценивает каждое из Case
операторов и запускает код для каждого из них, который является истинным. Но на самом деле он оценивает их один за другим и запускает код только для первого из них, которое является истинным. В этом отношении синтаксис для ( If
) намного яснее If...Else If...Else If...Else
.
Одно из основных средств экономии времени, которое я использую постоянно, - это ключевое слово With :
With ReallyLongClassName
.Property1 = Value1
.Property2 = Value2
...
End With
Я просто не люблю печатать больше, чем нужно!
Лучший и простой парсер CSV:
Microsoft.VisualBasic.FileIO.TextFieldParser
Добавив ссылку на Microsoft.VisualBasic, это можно будет использовать на любом другом языке .Net, например C #.
(РЕДАКТИРОВАТЬ: Узнайте больше здесь: всегда ли мне использовать операторы AndAlso и OrElse? )
Статические члены в методах.
Например:
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-член класса; элементы, объявленные таким образом, также гарантированно будут потокобезопасными. В этом сценарии это не имеет значения, поскольку выражение никогда не изменится, но есть и другие, где это может измениться.
В 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
Мне очень нравится пространство имен «My», которое было введено в Visual Basic 2005. My - это ярлык для нескольких групп информации и функций. Он обеспечивает быстрый и интуитивно понятный доступ к следующим типам информации:
Обработка событий редко бывает полезной, но ее можно сильно настроить:
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
Я только что нашел статью, в которой говорится о "!" оператор, также известный как «оператор поиска по словарю». Вот отрывок из статьи по адресу: 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». К счастью, поскольку в языке нет места, где действительны два идентификатора подряд, мы просто ввели правило, что если следующий символ после! является началом идентификатора, мы считаем! быть оператором, а не типом.
Это встроено, и это явное преимущество перед 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
Рассмотрим следующее объявление события
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
Если вам нужно, чтобы имя переменной соответствовало ключевому слову, заключите его в квадратные скобки. Не включенные в другие группы. хотя это лучшая практика, но ее можно использовать с умом.
например
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
Есть несколько ответов о 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>
тег; вы можете использовать любой тег, который вам нравится.)
<q>
был бы хорошим тегом, похожим на использование в Perl / Ruby. В любом случае, это неплохая идиома. ЛАЙК!
DateTime можно инициализировать, заключив дату в #
Dim independanceDay As DateTime = #7/4/1776#
Вы также можете использовать вывод типа вместе с этим синтаксисом
Dim independanceDay = #7/4/1776#
Это намного приятнее, чем использовать конструктор
Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
У вас может быть 2 строки кода всего в одной строке. следовательно:
Dim x As New Something : x.CallAMethod
Call (New Something).CallAMethod()
Дополнительные параметры
Варианты намного проще, чем создавать новые перегрузки, такие как:
Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
Console.Writeline(msg)
''//do stuff
End Function
Заглавный регистр в VB.Net можно получить с помощью старого VB6 fxn:
StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
Свойства с параметрами
Я занимался программированием на 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