Я довольно много узнал о просмотре Скрытых функций из С# и был удивлен, когда я не мог найти что-то аналогично для 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)
Imports
должен быть. ;-) Каким-то образом эта ошибка осталась незамеченной (и набрала 28 голосов) почти целый год.
О! и не забывайте XML Literals.
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, где каждое поле был в кавычках. Это не было бы весело , чтобы избежать всех этих цитат вручную в моих тестовых строк.)
DirectCast
DirectCast
- это чудо. На поверхности он работает аналогично оператору CType
в том смысле, что он преобразует объект из одного типа в другой. Однако он работает с гораздо более строгим набором правил. CType
Поэтому фактическое поведение часто непрозрачно и совсем не видно, какое преобразование выполнено.
DirectCast
поддерживает только две различные операции:
Любые другие действия не будут работать (например, при попытке удалить Integer
в Double
) и приведет к ошибке времени компиляции/времени выполнения (в зависимости от ситуации и того, что может быть обнаружено при проверке статического типа). Поэтому я использую DirectCast
, когда это возможно, так как это лучше всего отражает мое намерение: в зависимости от ситуации я либо хочу, чтобы было освобождено значение известного типа или выполнялось повышение. Конец истории.
Использование CType
, с другой стороны, оставляет читателя кода недоумевающим, что программист действительно намеревался, поскольку он разрешает все виды различных операций, включая вызов пользовательского кода.
Почему это скрытая функция? Команда VB опубликовала руководство 1 которое препятствует использованию DirectCast
(даже если оно действительно быстрее!), Чтобы сделать код более однородным. Я утверждаю, что это неправильная рекомендация, которая должна быть отменена: По возможности пользуйтесь DirectCast
более общим оператором CType
. Это делает код намного понятнее. CType
, с другой стороны, следует вызывать только в том случае, если это действительно предназначено, т.е. когда суживающий оператор CType
(см. перегрузка оператора).
1) Я не могу придумать ссылку на руководство, но я нашел Пол Вик взял он (главный разработчик команды VB):
В реальном мире вы вряд ли заметите разницу, так что вы можете пойти с более гибкими операциями преобразования, такими как CType, CInt и т.д.
(EDIT от Zack: Подробнее здесь: Как мне сделать в VB.NET?)
Инициализация объекта тоже там!
Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
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
Лучший и простой парсер CSV:
Microsoft.VisualBasic.FileIO.TextFieldParser
Добавив ссылку на Microsoft.VisualBasic, это может быть использовано на любом другом языке .Net. С#
Одна важная экономия времени, которую я использую все время, - это ключевое слово С:
With ReallyLongClassName
.Property1 = Value1
.Property2 = Value2
...
End With
Мне просто не нравится печатать больше, чем нужно!
(EDIT: Подробнее здесь: Должен ли я всегда использовать операторы 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
Мне очень нравится "Мое" пространство имен, которое было представлено в Visual Basic 2005. Я - ярлык для нескольких групп информации и функциональности. Он обеспечивает быстрый и интуитивно понятный доступ к следующим типам информации:
Статические элементы в методах.
Например:
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
Кроме того, это не то же самое, что просто объявить его как общий член класса; объекты, объявленные таким образом, также гарантируют поточность. В этом случае не имеет значения, так как выражение никогда не изменится, но есть и другие, где это возможно.
Хотя редко бывает полезно, обработка событий может быть сильно изменена:
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"))
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
Рассмотрим следующее объявление события
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
Если вам нужно имя переменной для соответствия ключевому слову, заключите его в скобки. Не указано. однако лучше всего - но его можно использовать с умом.
например.
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
Имена импорта также в значительной степени неизвестны:
Import winf = System.Windows.Forms
''Later
Dim x as winf.Form
Есть несколько ответов о 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
Множество Stack/group с использованием операторов вместе:
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
Справедливости ради, вы можете сделать это и на С#. Но многие люди не знают об этом ни на одном из языков.
Свойства с параметрами
Я занимаюсь программированием на С# и обнаружил недостающую особенность 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
Заголовок в VB.Net может быть достигнут старым VB6 fxn:
StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
Одна из функций, которые я нашел очень полезными и помогла решить множество ошибок, явно передает аргументы в функции, особенно при использовании необязательных.
Вот пример:
Public Function DoSomething(byval x as integer, optional y as boolean=True, optional z as boolean=False)
' ......
End Function
тогда вы можете вызвать его следующим образом:
DoSomething(x:=1, y:=false)
DoSomething(x:=2, z:=true)
or
DoSomething(x:=3,y:=false,z:=true)
Это намного чище и без ошибок, затем вызывает функцию, подобную этой
DoSomething(1,true)
Обратите внимание на использование when
в строке Catch ex As IO.FileLoadException When attempt < 3
Do
Dim attempt As Integer
Try
''// something that might cause an error.
Catch ex As IO.FileLoadException When attempt < 3
If MsgBox("do again?", MsgBoxStyle.YesNo) = MsgBoxResult.No Then
Exit Do
End If
Catch ex As Exception
''// if any other error type occurs or the attempts are too many
MsgBox(ex.Message)
Exit Do
End Try
''// increment the attempt counter.
attempt += 1
Loop
Недавно просмотренный в VbRad
Если вы никогда не знали о следующем, вы действительно не поверите, что это правда, это действительно то, что С# не хватает большого времени:
(Он называется XML-литералами)
Imports <xmlns:xs="System">
Module Module1
Sub Main()
Dim xml =
<root>
<customer id="345">
<name>John</name>
<age>17</age>
</customer>
<customer id="365">
<name>Doe</name>
<age>99</age>
</customer>
</root>
Dim id = 1
Dim name = "Beth"
DoIt(
<param>
<customer>
<id><%= id %></id>
<name><%= name %></name>
</customer>
</param>
)
Dim names = xml...<name>
For Each n In names
Console.WriteLine(n.Value)
Next
For Each customer In xml.<customer>
Console.WriteLine("{0}: {1}", customer.@id, customer.<age>.Value)
Next
Console.Read()
End Sub
Private Sub CreateClass()
Dim CustomerSchema =
XDocument.Load(CurDir() & "\customer.xsd")
Dim fields =
From field In CustomerSchema...<xs:element>
Where field.@type IsNot Nothing
Select
Name = field.@name,
Type = field.@type
Dim customer =
<customer> Public Class Customer
<%= From field In fields Select <f>
Private m_<%= field.Name %> As <%= GetVBPropType(field.Type) %></f>.Value %>
<%= From field In fields Select <p>
Public Property <%= field.Name %> As <%= GetVBPropType(field.Type) %>
Get
Return m_<%= field.Name %>
End Get
Set(ByVal value As <%= GetVBPropType(field.Type) %>)
m_<%= field.Name %> = value
End Set
End Property</p>.Value %>
End Class</customer>
My.Computer.FileSystem.WriteAllText("Customer.vb",
customer.Value,
False,
System.Text.Encoding.ASCII)
End Sub
Private Function GetVBPropType(ByVal xmlType As String) As String
Select Case xmlType
Case "xs:string"
Return "String"
Case "xs:int"
Return "Integer"
Case "xs:decimal"
Return "Decimal"
Case "xs:boolean"
Return "Boolean"
Case "xs:dateTime", "xs:date"
Return "Date"
Case Else
Return "'TODO: Define Type"
End Select
End Function
Private Sub DoIt(ByVal param As XElement)
Dim customers =
From customer In param...<customer>
Select New Customer With
{
.ID = customer.<id>.Value,
.FirstName = customer.<name>.Value
}
For Each c In customers
Console.WriteLine(c.ToString())
Next
End Sub
Private Class Customer
Public ID As Integer
Public FirstName As String
Public Overrides Function ToString() As String
Return <string>
ID : <%= Me.ID %>
Name : <%= Me.FirstName %>
</string>.Value
End Function
End Class
End Module
'Results:
ID : 1
Name : Beth
John
Doe
345: 17
365: 99
Взгляните на XML-литровые советы/рекомендации Бет Масси.
У вас может быть значение If в одной строке.
If True Then DoSomething()
В отличие от break
на языках C в VB вы можете Exit
или Continue
блока, который хотите:
For i As Integer = 0 To 100
While True
Exit While
Select Case i
Case 1
Exit Select
Case 2
Exit For
Case 3
Exit While
Case Else
Exit Sub
End Select
Continue For
End While
Next
Здесь смешной, которого я не видел; Я знаю, что он работает в VS 2008, по крайней мере:
Если вы случайно закончили строку VB точкой с запятой, потому что вы делали слишком много С#, точка с запятой автоматически удаляется. На самом деле это невозможно (опять же, в VS 2008), чтобы случайно завершить линию VB точкой с запятой. Попробуйте!
(Это не идеально, если вы набираете точку с запятой на полпути через ваше окончательное имя класса, она не будет автозаполнять имя класса.)
При объявлении массива в vb.net всегда используйте синтаксис "0 to xx".
Dim b(0 to 9) as byte 'Declares an array of 10 bytes
Он очень четко описывает диапазон массива. Сравните его с эквивалентным
Dim b(9) as byte 'Declares another array of 10 bytes
Даже если вы знаете, что второй пример состоит из 10 элементов, это просто не кажется очевидным. И я не помню, сколько раз, когда я видел код от программиста, который хотел выше, но вместо этого писал
Dim b(10) as byte 'Declares another array of 10 bytes
Это, конечно, совершенно неправильно. Поскольку b (10) создает массив из 11 байтов. И это может легко вызвать ошибки, поскольку они выглядят правильно для всех, кто не знает, что искать.
Синтаксис "от 0 до xx" также работает с ниже
Dim b As Byte() = New Byte(0 To 9) {} 'Another way to create a 10 byte array
ReDim b(0 to 9) 'Assigns a new 10 byte array to b
Используя полный синтаксис, вы также продемонстрируете всем, кто читает ваш код в будущем, что вы знали, что делаете.
Вы можете использовать зарезервированное ключевое слово для свойств и имен переменных, если вы окружаете имя с помощью [и]
Public Class Item
Private Value As Integer
Public Sub New(ByVal value As Integer)
Me.Value = value
End Sub
Public ReadOnly Property [String]() As String
Get
Return Value
End Get
End Property
Public ReadOnly Property [Integer]() As Integer
Get
Return Value
End Get
End Property
Public ReadOnly Property [Boolean]() As Boolean
Get
Return Value
End Get
End Property
End Class
'Real examples:
Public Class PropertyException : Inherits Exception
Public Sub New(ByVal [property] As String)
Me.Property = [property]
End Sub
Private m_Property As String
Public Property [Property]() As String
Get
Return m_Property
End Get
Set(ByVal value As String)
m_Property = value
End Set
End Property
End Class
Public Enum LoginLevel
[Public] = 0
Account = 1
Admin = 2
[Default] = Account
End Enum
IIf(False, MsgBox("msg1"), MsgBox("msg2"))
Каков результат? две коробки сообщений!!!! Это происходит потому, что функция IIf оценивает оба параметра при достижении функции.
У VB есть новый оператор If (как оператор С#?:):
If(False, MsgBox("msg1"), MsgBox("msg2"))
Покажет только второй msgbox.
в общем, я бы рекомендовал заменить все IIF в вашем коде vb, если вы не хотите, чтобы он обдумывал оба элемента:
Dim value = IIf(somthing, LoadAndGetValue1(), LoadAndGetValue2())
вы можете быть уверены, что оба значения загружены.
Как и в ответе Parsa's, как оператор имеет лоты вещей, которые он может сопоставлять поверх простых подстановочных знаков. Я чуть не упал со стула, читая MSDN doco на нем:-)
Выберите Случай вместо нескольких операторов If/ElseIf/Else.
Предположим, что в этом примере объекты простой геометрии:
Function GetToString(obj as SimpleGeomertyClass) as String
Select Case True
Case TypeOf obj is PointClass
Return String.Format("Point: Position = {0}", _
DirectCast(obj,Point).ToString)
Case TypeOf obj is LineClass
Dim Line = DirectCast(obj,LineClass)
Return String.Format("Line: StartPosition = {0}, EndPosition = {1}", _
Line.StartPoint.ToString,Line.EndPoint.ToString)
Case TypeOf obj is CircleClass
Dim Line = DirectCast(obj,CircleClass)
Return String.Format("Circle: CenterPosition = {0}, Radius = {1}", _
Circle.CenterPoint.ToString,Circle.Radius)
Case Else
Return String.Format("Unhandled Type {0}",TypeName(obj))
End Select
End Function
В VB8 и предыдущих версиях, если вы не указали какой-либо тип для введенной переменной, тип объекта был автоматически обнаружен. В VB9 (2008) Dim
будет действовать как ключевое слово С# var
, если для параметра Infer установлено значение On (по умолчанию)
Ключевое слово Nothing может означать значение по умолчанию (T) или null, в зависимости от контекста. Вы можете использовать это, чтобы сделать очень интересный метод:
'''<summary>Returns true for reference types, false for struct types.</summary>'
Public Function IsReferenceType(Of T)() As Boolean
Return DirectCast(Nothing, T) Is Nothing
End Function
GetType(T).IsValueType
.
В отличие от С#, в VB вы можете полагаться на значения по умолчанию для элементов, не подлежащих обнулению:
Sub Main()
'Auto assigned to def value'
Dim i As Integer '0'
Dim dt As DateTime '#12:00:00 AM#'
Dim a As Date '#12:00:00 AM#'
Dim b As Boolean 'False'
Dim s = i.ToString 'valid
End Sub
В то время как в С# это будет ошибка компилятора:
int x;
var y = x.ToString(); //Use of unassigned value
Ключевое слово MyClass предоставляет способ ссылаться на члены экземпляра класса, как первоначально реализовано, игнорируя переопределения производных классов.
может быть эта ссылка должна помочь
http://blogs.msdn.com/vbteam/archive/2007/11/20/hidden-gems-in-visual-basic-2008-amanda-silver.aspx
Также важно помнить, что проекты VB.NET по умолчанию имеют корневое пространство имен, которое является частью свойств проектов. По умолчанию это корневое пространство имен будет иметь то же имя, что и проект. При использовании структуры блока пространства имен имена фактически добавляются к этому пространству имен корней. Например: если проект называется MyProject, мы можем объявить переменную как:
Private obj As MyProject.MyNamespace.MyClass
Чтобы изменить корневое пространство имен, используйте пункт меню "Проект → Свойства". Корневое пространство имен также может быть очищено, что означает, что все блоки пространства имен становятся корневым уровнем для кода, который они содержат.
VB также предлагает оператор OnError. Но в наши дни это не так много.
On Error Resume Next
' Or'
On Error GoTo someline
код >
On Error Resume Next
- правильная вещь, она гораздо менее загромождена, чем Try Catch для каждого оператора.
Привязка пространств имен
Imports Lan = Langauge
Хотя он не уникален для VB.Net, он часто забывается при конфликтах пространства имен.
Недействительные даты! Это особенно полезно в тех случаях, когда у вас есть данные, поступающие в/из базы данных (в данном случае MSSQL Server). У меня есть две процедуры, чтобы дать мне параметр SmallDateTime, заполненный значением. Один из них принимает простую старую дату и тесты, чтобы увидеть, есть ли в ней значение, назначая дату по умолчанию. Другая версия принимает Nullable(Of Date)
, чтобы я мог оставить дату бесполезной, принимая все, что было по умолчанию, из хранимой процедуры
<System.Diagnostics.DebuggerStepThrough> _
Protected Function GP(ByVal strName As String, ByVal dtValue As Date) As SqlParameter
Dim aParm As SqlParameter = New SqlParameter
Dim unDate As Date
With aParm
.ParameterName = strName
.Direction = ParameterDirection.Input
.SqlDbType = SqlDbType.SmallDateTime
If unDate = dtValue Then 'Unassigned variable
.Value = "1/1/1900 12:00:00 AM" 'give it a default which is accepted by smalldatetime
Else
.Value = CDate(dtValue.ToShortDateString)
End If
End With
Return aParm
End Function
<System.Diagnostics.DebuggerStepThrough()> _
Protected Function GP(ByVal strName As String, ByVal dtValue As Nullable(Of Date)) As SqlParameter
Dim aParm As SqlParameter = New SqlParameter
Dim unDate As Date
With aParm
.ParameterName = strName
.Direction = ParameterDirection.Input
.SqlDbType = SqlDbType.SmallDateTime
If dtValue.HasValue = False Then
'// it nullable, so has no value
ElseIf unDate = dtValue.Value Then 'Unassigned variable
'// still, it nullable for a reason, folks!
Else
.Value = CDate(dtValue.Value.ToShortDateString)
End If
End With
Return aParm
End Function
Private Sub Button1_Click(ByVal sender As Button, ByVal e As System.EventArgs)
Handles Button1.Click
sender.Enabled = True
DisableButton(sender)
End Sub
Private Sub Disable(button As Object)
button.Enabled = false
End Sub
В этом фрагменте у вас есть 2 (возможно, больше?) вещей, которые вы никогда не сможете сделать в С#:
Кроме того, в С# вы не можете использовать ожидаемые функции на объекте - на С# вы можете мечтать об этом (теперь они сделали динамическое ключевое слово, но оно далеко от VB). В С#, если вы напишете (новый объект()). Включено, вы получите сообщение об ошибке, что тип объекта не имеет метода "Включено". Теперь я не тот, кто порекомендует вас, если это будет безопасно или нет, информация предоставлена КАК ЕСТЬ, сделайте сами по себе, по-прежнему оставайтесь на автобусе, иногда (например, при работе с объектами COM) это так хорошо. Я лично всегда пишу (отправитель As Button), когда ожидаемое значение, безусловно, является кнопкой.
На самом деле, кроме того: возьмите этот пример:
Private Sub control_Click(ByVal sender As Control, ByVal e As System.EventArgs)
Handles TextBox1.Click, CheckBox1.Click, Button1.Click
sender.Text = "Got it?..."
End Sub
Невозможно Явно реализовать элементы интерфейса в VB, но возможно реализовать их с другим именем.
Interface I1
Sub Foo()
Sub TheFoo()
End Interface
Interface I2
Sub Foo()
Sub TheFoo()
End Interface
Class C
Implements I1, I2
Public Sub IAmFoo1() Implements I1.Foo
' Something happens here'
End Sub
Public Sub IAmFoo2() Implements I2.Foo
' Another thing happens here'
End Sub
Public Sub TheF() Implements I1.TheFoo, I2.TheFoo
' You shouldn't yell!'
End Sub
End Class
Пожалуйста, проголосуйте за эту функцию в Microsoft Connect.
Вы можете использовать REM, чтобы прокомментировать строку вместо ' , Не супер полезно, но помогает важным комментариям без использования "!!!!!!!" или что-то еще.
REM
не рекомендуется. Команда VB рассматривает возможность полного удаления его из следующей версии. Таким образом, перспективный код лучше не использовать.
Я не знаю, как спрятал бы ты его, но If
может рассчитывать.
Он очень похож, в некотором смысле, на оператор ?:
(тройной) или ??
на множестве C-подобных языков. Однако важно отметить, что он действительно оценивает все параметры, поэтому важно не передавать ничего, что может вызвать исключение (если вы этого не хотите) или что-либо, что может вызвать непреднамеренные побочные эффекты.
Использование:
Dim result = If(condition, valueWhenTrue, valueWhenFalse)
Dim value = If(obj, valueWhenObjNull)
Документация кода
''' <summary>
'''
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub
Различия между ключевыми словами ByVal и ByRef:
Module Module1
Sub Main()
Dim str1 = "initial"
Dim str2 = "initial"
DoByVal(str1)
DoByRef(str2)
Console.WriteLine(str1)
Console.WriteLine(str2)
End Sub
Sub DoByVal(ByVal str As String)
str = "value 1"
End Sub
Sub DoByRef(ByRef str As String)
str = "value 2"
End Sub
End Module
'Results:
'initial
'value 2
Когда-то основные пользователи не вводили никаких переменных. Они представили их, просто используя их. VB Option Explicit был введен только для того, чтобы вы не ошиблись при вводе какой-либо переменной из-за плохой типизации. Вы всегда можете переключить его на Off, испытать дни, которые мы работали с Basic.
Раньше я очень любил необязательные параметры функции, но теперь я использую их меньше, потому что мне нужно многократно перемещаться между С# и VB. Когда С# поддержит их? С++ и даже C имели их (вроде)!
Дополнительные аргументы снова!
Function DoSmtg(Optional a As string, b As Integer, c As String)
'DoSmtg
End
' Call
DoSmtg(,,"c argument")
DoSmtg(,"b argument")
Атрибуты для методов! Например, свойство, которое не должно быть доступно во время разработки, может быть 1) скрыто от окна свойств, 2) не сериализовано (особенно раздражает для пользовательских элементов управления или для элементов управления, которые загружаются из базы данных):
<System.ComponentModel.Browsable(False), _
System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden), _
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always), _
System.ComponentModel.Category("Data")> _
Public Property AUX_ID() As String
<System.Diagnostics.DebuggerStepThrough()> _
Get
Return mAUX_ID
End Get
<System.Diagnostics.DebuggerStepThrough()> _
Set(ByVal value As String)
mAUX_ID = value
End Set
End Property
Вставка DebuggerStepThrough()
также очень полезна, если вы выполняете какую-либо отладку (обратите внимание, что вы все равно можете поставить точку прерывания внутри функции или что-то еще, но вы не можете один шаг через эту функцию).
Кроме того, возможность помещать вещи в категории (например, "Данные" ) означает, что если вы хотите, чтобы свойство отображалось в окне инструментов свойств, это конкретное свойство будет отображаться в этой категории.
Sub Main()
Select Case "value to check"
'Check for multiple items at once:'
Case "a", "b", "asdf"
Console.WriteLine("Nope...")
Case "value to check"
Console.WriteLine("Oh yeah! thass what im talkin about!")
Case Else
Console.WriteLine("Nah :'(")
End Select
Dim jonny = False
Dim charlie = True
Dim values = New String() {"asdff", "asdfasdf"}
Select Case "asdfasdf"
'You can perform boolean checks that has nothing to do with your var.,
'not that I would recommend that, but it exists.'
Case values.Contains("ddddddddddddddddddddddd")
Case True
Case "No sense"
Case Else
End Select
Dim x = 56
Select Case x
Case Is > 56
Case Is <= 5
Case Is <> 45
Case Else
End Select
End Sub
Ключевое слово Me
Ключевое слово "Я" уникально в VB.Net. Я знаю, что это довольно часто, но есть разница между "Я" и эквивалентом С# "this". Разница в "this" только для чтения, а "Me" - нет. Это полезно в конструкторах, где у вас есть экземпляр переменной, для которой вы хотите, чтобы переменная была сконструирована так же, как вы можете просто установить "Me = TheVariable", а не С#, где вам нужно будет скопировать каждое поле переменной вручную (что может быть ужасным, если есть много полей и склонность к ошибкам). Обходной путь С# состоял бы в том, чтобы выполнить назначение вне конструктора. Это означает, что теперь, если объект самосортирован для полного объекта, вам теперь нужна другая функция.
Me
только для чтения, как this
.
'Me' cannot be the target of an assignment