Aprendi bastante a navegar nos Recursos ocultos do C # e fiquei surpreso quando não consegui encontrar algo semelhante para o VB.NET.
Então, quais são alguns dos seus recursos ocultos ou menos conhecidos?
Aprendi bastante a navegar nos Recursos ocultos do C # e fiquei surpreso quando não consegui encontrar algo semelhante para o VB.NET.
Então, quais são alguns dos seus recursos ocultos ou menos conhecidos?
Respostas:
o Exception When
cláusula é amplamente desconhecida.
Considere isto:
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
SUm dos recursos ocultos reais do VB é a completionlist
tag de documentação XML que pode ser usada para criarEnum
tipos com funcionalidade estendida. Esse recurso não funciona em C #, no entanto.
Um exemplo de um código recente meu:
'
''' <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
Agora, ao atribuir um valor a uma variável declarada como Rule
, o IDE oferece uma lista IntelliSense de possíveis valores deRuleTemplates
.
Como esse é um recurso que depende do IDE, é difícil mostrar como isso fica quando você o usa, mas usarei uma captura de tela:
Lista de conclusão em ação http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png
De fato, o IntelliSense é 100% idêntico ao que você obtém ao usar um Enum
.
friend
ou usando a mesma classe que o enum: em Rule
vez de RuleTemplate
.
Você notou o operador de comparação Like?
Dim b As Boolean = "file.txt" Like "*.txt"
Mais do 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*"
O VB conhece um tipo primitivo de aliases de typedef
via Import
:
Imports S = System.String
Dim x As S = "Hello"
Isso é mais útil quando usado em conjunto com tipos genéricos:
Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)
Imports
deveria ser. ;-) De alguma forma, esse erro passou despercebido (e obteve 28 upvotes) por quase um ano inteiro.
Imports Assert = xUnit.Assert
Oh! e não se esqueça de literais 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
(Eu encontrei este especialmente útil quando se escreve testes em analisar arquivos CSV onde cada campo foi entre aspas Seria. Não ter sido divertido para escapar de todas aquelas citações por mão na minha linhas de teste).
A inicialização do objeto também está lá!
Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
DirectCast
DirectCast
é uma maravilha. Na superfície, funciona de maneira semelhante àCType
operador, pois converte um objeto de um tipo para outro. No entanto, ele funciona com um conjunto de regras muito mais rigoroso. CType
Portanto, o comportamento real geralmente é opaco e não é de todo evidente que tipo de conversão é executada.
DirectCast
suporta apenas duas operações distintas:
Qualquer outra conversão não funcionará (por exemplo, tentando desmarcar uma Integer
a Double
) e resultará em um erro de tempo de compilação / tempo de execução (dependendo da situação e do que pode ser detectado pela verificação de tipo estático). Por isso usoDirectCast
sempre que possível, pois isso captura minha melhor intenção: dependendo da situação, quero desmarcar um valor do tipo conhecido ou executar um upcast. Fim da história.
O uso CType
, por outro lado, deixa o leitor do código imaginando o que o programador realmente pretendia, porque ele resolve todos os tipos de operações diferentes, incluindo a chamada de código definido pelo usuário.
Por que isso é um recurso oculto? A equipe do VB publicou uma diretriz 1 que desencoraja o uso de DirectCast
(mesmo que seja realmente mais rápido!) Para tornar o código mais uniforme. Argumento que essa é uma orientação ruim que deve ser revertida: sempre que possível, favorece DirectCast
o CType
operador mais geral . Isso torna o código muito mais claro. CType
, por outro lado, só deve ser chamado se isso for realmente pretendido, ou seja, quando um CType
operador de restrição (cf. sobrecarga de operador ) deve ser chamado.
1) Não consigo encontrar um link para a diretriz, mas descobri a opinião de Paul Vick (desenvolvedor chefe da equipe VB):
No mundo real, você dificilmente notará a diferença, portanto é melhor usar os operadores de conversão mais flexíveis, como CType, CInt, etc.
(EDIT by Zack: Saiba mais aqui: como devo transmitir no VB.NET? )
TryCast
na época, porque eu tinha um osso para escolher com o uso generalizado de CType
.
TryCast
só funcionam em tipos de referência, conforme a documentação.
If
operador condicional e de coalescênciaEu não sei o quão oculto você chamaria isso, mas a função Iif ([expressão], [valor se verdadeiro], [valor se falso]) Como Objeto poderia contar.
Não é tão oculto quanto obsoleto ! O VB 9 possui o If
operador que é muito melhor e funciona exatamente como o operador condicional e de coalescência do C # (dependendo do que você deseja):
Dim x = If(a = b, c, d)
Dim hello As String = Nothing
Dim y = If(hello, "World")
Editado para mostrar outro exemplo:
Isso funcionará If()
, mas causará uma exceção comIIf()
Dim x = If(b<>0,a/b,0)
:?
operador de C e Perl , não é apenas uma versão simplificada.
Essa é boa. A instrução Select Case no VB.Net é muito poderosa.
Claro que existe o padrão
Select Case Role
Case "Admin"
''//Do X
Case "Tester"
''//Do Y
Case "Developer"
''//Do Z
Case Else
''//Exception case
End Select
Mas tem mais ...
Você pode fazer intervalos:
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
E ainda mais ...
Você pode (embora não seja uma boa idéia) fazer verificações booleanas em várias variáveis:
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
é que parece que ele avalia cada uma das Case
instruções e executa o código de cada uma que é verdadeira. Mas, na verdade, ele os avalia um por um e executa apenas o código do primeiro, o que é verdadeiro. A sintaxe para If
é muito mais clara nesse sentido ( If...Else If...Else If...Else
).
Uma grande economia de tempo que uso o tempo todo é a palavra-chave With :
With ReallyLongClassName
.Property1 = Value1
.Property2 = Value2
...
End With
Só não gosto de digitar mais do que preciso!
O melhor e mais fácil analisador de CSV:
Microsoft.VisualBasic.FileIO.TextFieldParser
Adicionando uma referência ao Microsoft.VisualBasic, isso pode ser usado em qualquer outro idioma .Net, por exemplo, C #
(EDIT: saiba mais aqui: devo usar sempre os operadores AndAlso e OrElse? )
Membros estáticos nos métodos.
Por exemplo:
Function CleanString(byval input As String) As String
Static pattern As New RegEx("...")
return pattern.Replace(input, "")
End Function
Na função acima, a expressão regular do padrão será criada apenas uma vez, não importa quantas vezes a função seja chamada.
Outro uso é manter uma instância de "random" por perto:
Function GetNextRandom() As Integer
Static r As New Random(getSeed())
Return r.Next()
End Function
Além disso, isso não é o mesmo que simplesmente declará-lo como um membro compartilhado da classe; itens declarados dessa maneira também são garantidos como seguros para threads. Não importa nesse cenário, pois a expressão nunca muda, mas há outras onde pode.
Na vb, há uma diferença entre estes operadores:
/
é Double
\
está Integer
ignorando o restante
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
Eu realmente gosto do namespace "My", que foi introduzido no Visual Basic 2005. My é um atalho para vários grupos de informações e funcionalidades. Ele fornece acesso rápido e intuitivo aos seguintes tipos de informações:
Embora raramente seja útil, a manipulação de eventos pode ser altamente personalizada:
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
Isso pode ser testado da seguinte maneira:
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
Acabei de encontrar um artigo falando sobre o "!" operador, também conhecido como "operador de pesquisa de dicionário". Aqui está um trecho do artigo em: http://panopticoncentral.net/articles/902.aspx
O nome técnico para o! operador é o "operador de pesquisa de dicionário". Um dicionário é qualquer tipo de coleção que é indexado por uma chave e não por um número, assim como as entradas em um dicionário de inglês são indexadas pela palavra que você deseja definir. O exemplo mais comum de um tipo de dicionário é o System.Collections.Hashtable, que permite adicionar pares (chave, valor) à hashtable e recuperar valores usando as chaves. Por exemplo, o código a seguir adiciona três entradas a uma hashtable e procura uma delas usando a chave "Carne de porco".
Dim Table As Hashtable = New Hashtable
Table("Orange") = "A fruit"
Table("Broccoli") = "A vegetable"
Table("Pork") = "A meat"
Console.WriteLine(Table("Pork"))
O ! O operador pode ser usado para procurar valores de qualquer tipo de dicionário que indexe seus valores usando cadeias. O identificador após o! é usado como a chave na operação de pesquisa. Portanto, o código acima poderia ter sido escrito:
Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)
O segundo exemplo é completamente equivalente ao primeiro, mas parece muito melhor, pelo menos aos meus olhos. Eu acho que existem muitos lugares onde! pode ser usado, especialmente quando se trata de XML e da Web, onde há apenas várias coleções indexadas por sequência de caracteres. Uma limitação infeliz é que a coisa que segue o! ainda precisa ser um identificador válido, portanto, se a string que você deseja usar como chave tiver algum caractere de identificador inválido, não será possível usar o! operador. (Você não pode, por exemplo, dizer "Tabela! AB $ CD = 5" porque $ não é legal em identificadores.) No VB6 e antes, você poderia usar colchetes para escapar de identificadores inválidos (por exemplo, "Tabela! [AB $ CD] "), mas quando começamos a usar colchetes para escapar de palavras-chave, perdemos a capacidade de fazer isso. Na maioria dos casos,
Para ser realmente técnico, x! Y funciona se x tiver uma propriedade padrão que use String ou Object como parâmetro. Nesse caso, x! Y é alterado para x.DefaultProperty ("y"). Uma observação interessante é que existe uma regra especial na gramática lexical da língua para fazer tudo funcionar. O ! O caractere também é usado como um caractere de tipo no idioma e os caracteres de tipo são consumidos antes dos operadores. Portanto, sem uma regra especial, x! Y seria digitalizado como "x! Y" em vez de "x! Y". Felizmente, como não há lugar no idioma em que dois identificadores seguidos sejam válidos, apenas introduzimos a regra de que, se o próximo caractere após o! é o início de um identificador, consideramos o! ser um operador e não um caractere de tipo.
Isso é interno e uma vantagem definitiva sobre o C #. A capacidade de implementar um método de interface sem precisar usar o mesmo nome.
Tal como:
Public Sub GetISCSIAdmInfo(ByRef xDoc As System.Xml.XmlDocument) Implements IUnix.GetISCSIInfo
End Sub
Forçando ByVal
No VB, se você agrupar seus argumentos em um conjunto extra de parênteses, poderá substituir a declaração ByRef do método e transformá-la em um ByVal. Por exemplo, o código a seguir produz 4, 5, 5 em vez de 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
Consulte Argumento não sendo modificado por chamada de procedimento - variável subjacente
Passando parâmetros por nome e, portanto, reordenando-os
Sub MyFunc(Optional msg as String= "", Optional displayOrder As integer = 0)
'Do stuff
End function
Uso:
Module Module1
Sub Main()
MyFunc() 'No params specified
End Sub
End Module
Também pode ser chamado usando a especificação de parâmetro ": =" em qualquer ordem:
MyFunc(displayOrder:=10, msg:="mystring")
A instrução Using é nova no VB 8, C # tinha desde o início. Chama descarte automaticamente para você.
Por exemplo
Using lockThis as New MyLocker(objToLock)
End Using
Os aliases de importação também são amplamente desconhecidos:
Import winf = System.Windows.Forms
''Later
Dim x as winf.Form
Considere a seguinte declaração de evento
Public Event SomethingHappened As EventHandler
Em C #, você pode verificar se há assinantes de eventos usando a seguinte sintaxe:
if(SomethingHappened != null)
{
...
}
No entanto, o compilador VB.NET não suporta isso. Na verdade, ele cria um campo de membro privado oculto que não é visível no IntelliSense:
If Not SomethingHappenedEvent Is Nothing OrElse SomethingHappenedEvent.GetInvocationList.Length = 0 Then
...
End If
Mais Informações:
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
Se você precisar de um nome de variável para corresponder ao de uma palavra-chave, coloque-o entre colchetes. Não ne. embora seja a melhor prática - mas pode ser usada com sabedoria.
por exemplo
Class CodeException
Public [Error] as String
''...
End Class
''later
Dim e as new CodeException
e.Error = "Invalid Syntax"
por exemplo, exemplo de comentários (@Pondidum):
Class Timer
Public Sub Start()
''...
End Sub
Public Sub [Stop]()
''...
End Sub
Há algumas respostas sobre literais XML, mas não sobre este caso específico:
Você pode usar literais XML para incluir literais de string que, de outra forma, precisariam ser escapados. Literais de string que contêm aspas duplas, por exemplo.
Em vez disso:
Dim myString = _
"This string contains ""quotes"" and they're ugly."
Você consegue fazer isso:
Dim myString = _
<string>This string contains "quotes" and they're nice.</string>.Value
Isso é especialmente útil se você estiver testando um literal para análise de CSV:
Dim csvTestYuck = _
"""Smith"", ""Bob"", ""123 Anywhere St"", ""Los Angeles"", ""CA"""
Dim csvTestMuchBetter = _
<string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value
(Você não precisa usar a <string>
tag, é claro; pode usar qualquer tag que desejar.)
<q>
seria uma boa tag, semelhante ao uso em Perl / Ruby. Enfim, essa é uma linguagem legal. GOSTAR!
O DateTime pode ser inicializado cercando sua data com #
Dim independanceDay As DateTime = #7/4/1776#
Você também pode usar a inferência de tipo junto com esta sintaxe
Dim independanceDay = #7/4/1776#
Isso é muito melhor do que usar o construtor
Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
Você pode ter 2 linhas de código em apenas uma linha. conseqüentemente:
Dim x As New Something : x.CallAMethod
Call (New Something).CallAMethod()
Parâmetros opcionais
Os opcionais são muito mais fáceis do que criar uma nova sobrecarga, como:
Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
Console.Writeline(msg)
''//do stuff
End Function
O Case Title no VB.Net pode ser obtido por um antigo VB6 fxn:
StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
Propriedades com parâmetros
Eu tenho feito alguma programação em C # e descobri um recurso que estava faltando no VB.Net, mas não foi mencionado aqui.
Um exemplo de como fazer isso (assim como a limitação de c #) pode ser visto em: Usando as propriedades típicas de configuração definida em C # ... com parâmetros
Eu extraí o código dessa resposta:
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