Я довольно много узнал о просмотре Скрытых функций из С# и был удивлен, когда я не мог найти что-то аналогично для VB.NET.
Итак, каковы некоторые из его скрытых или менее известных функций?
Я довольно много узнал о просмотре Скрытых функций из С# и был удивлен, когда я не мог найти что-то аналогично для 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
с расширенной функциональностью. Однако эта функция не работает на С#.
Один пример из моего последнего кода:
'
''' <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 Literals.
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
, когда это возможно, так как это лучше всего отражает мое намерение: в зависимости от ситуации я либо хочу, чтобы было освобождено значение известного типа или выполнялось повышение. Конец истории.
Использование CType
, с другой стороны, оставляет читателя кода недоумевающим, что программист действительно намеревался, поскольку он разрешает все виды различных операций, включая вызов пользовательского кода.
Почему это скрытая функция? Команда VB опубликовала руководство 1 которое препятствует использованию DirectCast
(даже если оно действительно быстрее!), Чтобы сделать код более однородным. Я утверждаю, что это неправильная рекомендация, которая должна быть отменена: По возможности пользуйтесь DirectCast
более общим оператором CType
. Это делает код намного понятнее. CType
, с другой стороны, следует вызывать только в том случае, если это действительно предназначено, т.е. когда суживающий оператор CType
(см. перегрузка оператора).
1) Я не могу придумать ссылку на руководство, но я нашел Пол Вик взял он (главный разработчик команды VB):
В реальном мире вы вряд ли заметите разницу, так что вы можете пойти с более гибкими операциями преобразования, такими как CType, CInt и т.д.
(EDIT от Zack: Подробнее здесь: Как мне сделать в VB.NET?)
If
условный и коалесцирующий операторЯ не знаю, как бы вы это называли скрытым, но Iif ([expression], [value if true], [value if false]) Поскольку функция Object могла рассчитывать.
Это не столько скрыто, сколько устарело! VB 9 имеет оператор If
, который намного лучше и работает точно так же, как С# условный и коалесцирующий оператор (в зависимости от того, что вы хотите):
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
Одна важная экономия времени, которую я использую все время, - это ключевое слово С:
With ReallyLongClassName
.Property1 = Value1
.Property2 = Value2
...
End With
Мне просто не нравится печатать больше, чем нужно!
Лучший и простой парсер CSV:
Microsoft.VisualBasic.FileIO.TextFieldParser
Добавив ссылку на Microsoft.VisualBasic, это может быть использовано на любом другом языке .Net. С#
(EDIT: Подробнее здесь: Должен ли я всегда использовать операторы AndAlso и OrElse?)
Статические элементы в методах.
Например:
Function CleanString(byval input As String) As String
Static pattern As New RegEx("...")
return pattern.Replace(input, "")
End Function
В приведенной выше функции регулярное выражение шаблона будет создано только когда-либо независимо от того, сколько раз функция вызывается.
Другое использование - сохранить экземпляр "случайного":
Function GetNextRandom() As Integer
Static r As New Random(getSeed())
Return r.Next()
End Function
Кроме того, это не то же самое, что просто объявить его как общий член класса; объекты, объявленные таким образом, также гарантируют поточность. В этом случае не имеет значения, так как выражение никогда не изменится, но есть и другие, где это возможно.
В 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
Хотя редко бывает полезно, обработка событий может быть сильно изменена:
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
Мне очень нравится "Мое" пространство имен, которое было представлено в Visual Basic 2005. Я - ярлык для нескольких групп информации и функциональности. Он обеспечивает быстрый и интуитивно понятный доступ к следующим типам информации:
Я только что нашел статью о "!" оператор, также известный как "оператор поиска словаря". Вот выдержка из статьи: 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"))
The! оператор может быть использован для поиска значения из любого типа словаря, который индексирует свои значения с помощью строк. идентификатор после! используется как ключ в операции поиска. Итак выше код мог бы быть написано:
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", потому что $is not в идентификаторах.) В VB6 и прежде, вы можете использовать скобки для вывести недопустимые идентификаторы (т. "Таблица! [AB $CD]" ), но когда мы начали используя скобки для поиска ключевых слов, мы потерял способность сделать это. В большинстве случаев, однако, это не слишком ограничение.
Чтобы получить действительно технический, x! y работает, если x имеет свойство по умолчанию, которое принимает String или Object в качестве параметра. В в этом случае x! y заменяется на x.DefaultProperty( "у" ). Интересный Обратите внимание на то, что существует специальная правило в лексической грамматике язык, чтобы все это работало.! символ также используется как тип символ на языке и тип персонажи едят перед операторами. Поэтому без специального правила x! Y будет сканироваться как "x! y" вместо "x! y". К счастью, поскольку нет место на языке, где два идентификаторы в строке действительны, мы просто ввел правило, что если следующий символ после! это начале идентификатора, мы считаем! быть оператором, а не типом характер.
Это встроенное и определенное преимущество над С#. Возможность реализовать интерфейс Метод без использования того же имени.
Например:
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, С# имел его с самого начала. Он вызывает автоматический выбор для вас.
например.
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
В С# вы можете проверить подписчиков на события, используя следующий синтаксис:
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
Заголовок в VB.Net может быть достигнут старым VB6 fxn:
StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
Свойства с параметрами
Я занимаюсь программированием на С# и обнаружил недостающую особенность VB.Net, но не упоминался здесь.
Пример того, как это сделать (а также ограничение С#) можно увидеть по адресу: Использование типичных свойств get set в С#... с параметрами
Я выписал код из этого ответа:
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