Recursos ocultos do VB.NET?

121

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?

Sean Gough
fonte

Respostas:

128

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
histórico
fonte
9
útil se você deseja capturar um SQLException específico, digamos -2, que, se bem me lembro, é o tempo limite da rede: Catch ex como sqlException em que ex.code = -2
Pondidum
Uau! Acabei de ler isso e colocá-lo em uso imediatamente para simplificar um bloco try / catch que acabei de escrever na semana passada. Eu nunca novo isso existia.
John M Gant
1
+1 E aqui é onde o blog da equipe CLR NET explica por filtros de exceção são úteis blogs.msdn.com/clrteam/archive/2009/02/05/...
MarkJ
5
Não só isso está oculto, mas também não está disponível em C #.
Cheeso
82

personalizadas EnumS

Um dos recursos ocultos reais do VB é a completionlisttag 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 .

/EDITAR:

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.

Konrad Rudolph
fonte
Interessante - você poderia mostrar um exemplo de como isso ocorre quando você o consome?
Brian MacKay
Parece que alguém ainda pode criar sua própria regra chamando o construtor Rule diretamente? Se sim, e se você quisesse interromper isso, poderia declarar o construtor como "Amigo" em sua biblioteca?
Joel Coehoorn
Joel, no meu exemplo de código, eu não proíbe isso intencionalmente. Em vez disso, ofereço ao usuário algumas regras comuns e permito a criação de regras próprias e especializadas. Obviamente, você pode evitar isso marcando o construtor como friendou usando a mesma classe que o enum: em Rulevez de RuleTemplate.
9288 Konrad Rudolph
existe algum lugar com uma lista de usos de atributos úteis ocultos? este aqui parece incrível, mas ainda não tenho certeza de onde o usaria ou se poderia resolver uma queixa primária em alguns casos, sem a capacidade de ter um genérico restrito a enumerações.
Maslow
@ Maslow: não há atributo envolvido aqui. Esse é um comentário xml.
Joel Coehoorn
49

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*"
Eduardo Molteni
fonte
3
espere o que? Isso é novo para mim! Hmm, isso é muitíssimo melhor do que a alternativa com corda manipulação VB.NET: D
STW
.. !! Eu não sabia disso, embora trabalhasse em vários projetos vb.net! Característica interessante ...
Meta-Knight
woooooooooooooooooooooooow! obrigado! isso é impressionante! funciona no ELinq, DLinq também? e o XLinq?
Shimmy Weitzhandler 14/07/2009
@dotjoe Hmm? Não há nada de "preguiçoso" nesses globs.
27413 Josh Lee
Como isso funciona, o que está acontecendo sob o capô? É sinônimo de bibliotecas reg ex?
BrumScouse
48

Typedefs

O VB conhece um tipo primitivo de aliases de typedefvia 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)
Konrad Rudolph
fonte
2
mostre um exemplo: a palavra Import não é reconhecida no meu IDE.
218 Shimmy Weitzhandler
5
Importsdeveria ser. ;-) De alguma forma, esse erro passou despercebido (e obteve 28 upvotes) por quase um ano inteiro.
219 Konrad Rudolph
Eu sempre me perguntei como eu poderia fazer um novo "tipo" com padrões para um genérico! Legal!
eidylon
3
Importação, Importação, Importz, qualquer que seja! Nossa, você acha que lemos essas postagens antes de votá-las!
MarkJ
Excelente para a utilização em testes xUnit estúdio visuais, isto é,Imports Assert = xUnit.Assert
wheelibin
45

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>
Nescio
fonte
Era o que eu ia dizer. Na verdade, eu usei literais XML para um propósito em que não foi planejado. Usei-o para produzir Javascript ... swortham.blogspot.com/2009/03/vb-2008.html
Steve Wortham
9
Entre outras coisas, você pode usar XML Literals para contornar o feio escape de strings, por exemplo, quando você estiver usando strings que contenham aspas duplas. Basta colocar a corda dentro de um XML literal e chamar valor, como este: <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).
Ryan Lundy
2
@Kyralessa: +1, ótimo comentário. De fato, também é uma ótima maneira de especificar cadeias de linhas múltiplas (abraços instruções SQL, etc.).
Heinzi 27/12/2009
XML embutido é um dos piores recursos do VB.NET já criados. Fato sem fundamento.
Grant Thomas
39

A inicialização do objeto também está lá!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
Nescio
fonte
1
Eu não posso acreditar que eles foram com aparelho encaracolado. Já temos uma declaração With .. eles poderiam ter reutilizado essa sintaxe.
21339 Sam Ax
2
Eu sei, é feito apenas para mostrar-lhe que não há nenhum policial na estrada ... lol JK
Shimmy Weitzhandler
4
É o que acontece quando todos os escritores do compilador são eles próprios programadores de C / C ++. Eles continuam colocando a sintaxe C em outros idiomas porque não conseguem conceber que algo seja melhor.
RBarryYoung 19/09/09
38

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. CTypePortanto, o comportamento real geralmente é opaco e não é de todo evidente que tipo de conversão é executada.

DirectCast suporta apenas duas operações distintas:

  • Desembalagem de um tipo de valor e
  • upcasting na hierarquia de classes.

Qualquer outra conversão não funcionará (por exemplo, tentando desmarcar uma Integera 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 DirectCasto CTypeoperador 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 CTypeoperador 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? )

Konrad Rudolph
fonte
Na verdade, eu gosto do TryCast () um pouco melhor. Não lançará uma exceção, basta retornar Nothing se o elenco falhar. Se você espera que a conversão falhe com frequência, é mais rápido que o TypeOf x Is T ... DirectCast (x, T) e certamente mais rápido do que capturar a exceção se o DirectCast falhar.
Bob King
6
DirectCast () e TryCast () são inestimáveis ​​quando usados ​​corretamente como um par. O DirectCast () deve ser usado se sempre se espera que o objeto que está sendo convertido seja o tipo de destino (se não for, você receberá um erro, uma coisa boa, pois é uma situação inesperada). TryCast () deve ser usado se o objeto que está sendo convertido puder ser do tipo de destino ou de vários tipos de destino. Usar um ou outro exclusivamente resultará em sobrecarga extra (se tipo de x for y, a transmissão direta (x, y) é ineficiente) ou evitar erros válidos (usando TryCast () para casos em que o objeto sempre deve ser o tipo de destino)
STW
Yoooder: 100% correto. É uma pena que eu não mencionei TryCastna época, porque eu tinha um osso para escolher com o uso generalizado de CType.
5289 Konrad Rudolph
@ Maslow: é claro que não, pois as Enums são tipos de valor e TryCastsó funcionam em tipos de referência, conforme a documentação.
219 Konrad Rudolph
+1: Heh. Eu tenho que admitir, acabei de ler isso e pensei "Ah, sim, DirectCast, como eu esqueci disso?" E então eu o usei na minha próxima linha de código (como eu realmente não gosto do CType).
RBarryYoung 19/09/09
37

If operador condicional e de coalescência

Eu 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 Ifoperador 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)
Konrad Rudolph
fonte
Legal, eu não sabia disso! Eu usei o IIF ontem, então vou revisitar esse bloco de código.
21711 Sean Gough
4
Diga ao VS 2005 isso. Nem todos nós trabalhamos com os melhores e mais recentes.
Sam Erwin
3
@ Slough, absurdo. Esse método é 100% seguro para o tipo e retorna um objeto do mesmo tipo que seu (segundo e terceiro) argumento. Além disso, deve haver uma conversão ampliada entre os argumentos; caso contrário, haverá um erro de compilação porque os tipos não coincidem.
21978 Konrad Rudolph
1
Sim, a sua IIf (), que não é tipo seguro
Pondidum
2
@ Br.Bill De fato, é completamente equivalente ao :?operador de C e Perl , não é apenas uma versão simplificada.
Konrad Rudolph
32

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
histórico
fonte
5
Na verdade, você perdeu alguns: a) uso de "Select Case True" para testar mais de uma variável, b) uso do formulário "Case A, B, ..." e até c) aplicando o ":" alinhe a instrução de execução com a cláusula de condição (embora muitas não gostem disso).
RBarryYoung 19/09/09
6
Por favor, não use Select Case True. Basta usar uma instrução If.
Ryan Lundy
4
Acho Select Case True muito mais fácil de ler do que uma declaração ifelse gigante.
dwidel
O problema Select Case Trueé que parece que ele avalia cada uma das Caseinstruçõ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).
Ryan Lundy
31

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!

Jasha87
fonte
Mas também criar alguns erros escondidos, especialmente quando você tem Com dentro Com
Varun Mahajan
2
Eu nem sabia que você poderia colocar um novo With dentro de um existente. Isso é apenas desleixado!
Bob King
2Bob: não é desleixado, eu sugiro .. é apenas uma construção de linguagem a ser usada com cuidado. Para definir muitas propriedades em linhas sucessivas, é ótimo, mas encontrar.
ChrisA
2
Gostaria que o C # tivesse isso? Ou eu já estava dormindo e isso já está nas respostas dos recursos ocultos do C # ...? ;-)
peSHIr 15/01/09
1
@ Boo: Você está certo, mas ainda é um aborrecimento não poder adicioná-lo à lista de observação.
Meta-Knight
31

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 #

cjk
fonte
5
+1 É estranho como o pessoal do C # é executado no FileHelpers sem considerar isso. Tenho certeza que o FileHelpers é excelente, mas é uma dependência externa.
MarkJ
@MarkJ presumo que é por causa da ignorância
Nathan Koop
Eu pesquisei o inferno de tentar encontrar esta classe e nunca o fiz, obrigado por enlouquecer!
pingoo 24/05
26
  • Operadores lógicos AndAlso / OrElse

(EDIT: saiba mais aqui: devo usar sempre os operadores AndAlso e OrElse? )

Joel Coehoorn
fonte
Eu não chamaria isso de oculto, se o contato não é nada e também o contato.ContactId> 0 Então faça, se você usará e terá uma exceção lançada.
Shimmy Weitzhandler 14/07/2009
25

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.

Joel Coehoorn
fonte
1
Um uso disso é manter um contador que será incrementado toda vez que o método for chamado. Se a variável estiver marcada como Estática, ela não será reinicializada em cada chamada de método; ele será inicializado apenas na primeira chamada e, posteriormente, manterá seu valor.
22619 Ryan Lundy
Esta é a razão pela qual os membros da classe estáticos são nomeados "compartilhada" em VB.NET
Enrico Campidoglio
A estática é uma forma ruim no VB.NET ainda mais do que no VB clássico. As variáveis ​​estáticas devem ser evitadas sempre e sempre que possível.
21339 Sam Ax
6
@ Boo - isso é muito arrebatador. Qual a sua justificativa? Eu acho que variáveis ​​estáticas são úteis.
9139 MarkJ
4
Static, usado como nos exemplos acima, permite uma forma única de encapsulamento: variáveis ​​em nível de classe que possuem escopo em nível de método. Sem ele, você teria que criar uma variável no nível da classe que seria acessível a qualquer membro da classe, mesmo se você a estiver usando apenas em um método.
Ryan Lundy
25

Na vb, há uma diferença entre estes operadores:

/ é Double
\ está Integerignorando 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
Shimmy
fonte
1
Aprendi isso da maneira mais difícil ao tentar encontrar uma agulha em um milhão de linhas de código. divisão regular versus número inteiro. boa dica!
21139 Jason Irwin
23

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:

  • My.Computer : acesso a informações relacionadas ao computador, como sistema de arquivos, rede, dispositivos, informações do sistema etc. Ele fornece acesso a vários recursos muito importantes, incluindo My.Computer.Network, My.Computer.FileSystem e My. Impressoras.
  • Minha aplicação : acesso a informações relacionadas a um aplicativo específico, como nome, versão, diretório atual etc.
  • My.User : acesso a informações relacionadas ao usuário autenticado atual.
  • My.Resources : acesso aos recursos usados ​​pelo aplicativo que residem nos arquivos de recursos de uma maneira fortemente tipada.
  • My.Settings : acesso às definições de configuração do aplicativo de maneira fortemente tipada.
splattne
fonte
Isso é ótimo e todo cara do vb.net deve saber coisas no meu espaço para nome, é tão útil.
dr. evil
Meu. * FTW :).
dr. mal
3
É meio útil, mas eu odeio o nome idiota. Lembra-me deste secretgeek.net/refactvb.asp
MarkJ
23

Eventos Personalizados

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
Konrad Rudolph
fonte
parece legal, mas se eu precisar disso, acho que vou ter feito algo errado ;-). Parece apenas contra o princípio do KISS.
Chrissie1
4
É realmente muito útil quando você deseja garantir que cada coletor receba o evento, mesmo que um ou mais ative uma exceção.
1113 Jonathan Allen
Outro valor (acabei de ler no site do MSDN) é que, se sua classe lança muitos eventos, você pode forçá-la a usar uma tabela de hash / dicionário como um contêiner, em vez de declarar um campo para cada evento. msdn.microsoft.com/en-us/library/8627sbea(VS.71).aspx
torial
Legal. Eu pensei que esse era um dos recursos que separava C # e VB.NET (como em um deles, mas o outro não possui sintaxe). É bom pelo menos saber que eu estava errado a esse respeito.
peSHIr
21

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.

histórico
fonte
11
Esse é um desses recursos que eu usei e esqueci intencionalmente. Ele salva algumas teclas, mas mexe com o destaque e a legibilidade do meu código. esquecendo novamente certo .... NOW
STW
3
Interessante, mas não muito útil. É esse o tipo de coisa em que a equipe do VB trabalha em vez de adicionar recursos ausentes, como a palavra-chave yield? : P
Meta-Knight
5
Esta função é realizada para compatibilidade do VB3 (AFAIK)
Eduardo Molteni
1
as classes que implementam um índice com chave têm uma interface comum da qual herdam? como IKeyed da mesma maneira que contêineres indexados por número inteiro implementam IENumberable?
Maslow
2
Esse recurso também funciona com DataRows (ou seja, dr! ID), que é MUITO útil no LINQ to DataSets.
Paul
19

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
histórico
fonte
Tenho certeza de que você pode fazer algo assim em C #. No VB.NET é apenas forçado, e no C # é opcional?
Jesper Blad Jensen
5
Você também pode tornar o sub privado, o que é uma ótima maneira de ocultar coisas como as chamadas para versões obsoletas não genéricas das interfaces.
26711 Craig Gidney
3
Pode ser uma boa ideia. O exemplo clássico seria se você deseja um método Public Close que também atue como sua implementação Dispose para IDisposable.
9139 MarkJ # 09/09
1
Isso também é bastante útil se você implementar duas interfaces que compartilham um nome de método.
Eric Nicholson
Eu já vi isso e sempre desejei não ter visto. Não deve ser permitido.
FastAl
17

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

Chris Haas
fonte
6
Oh meu Deus ... essa é uma característica notável, embora eu não ache que eu saberia o que estava fazendo se eu lesse no código de outra pessoa. Se você tiver que comentar apenas para saber o que está fazendo, é possível que você tenha feito a variável throw away passar.
mattmc3
7
Na verdade, esse é um efeito colateral do uso de parênteses - os parênteses criam um valor temporário do que está dentro, mesmo que apenas um item. Esse efeito ME MATOU na vb6 - As sub-chamadas não pareciam parênteses, mas eu, vindo de C, instalei as parênteses. 6.0 explodiu em vários parâmetros, mas, para um subs de parâmetro, passou felizmente um valor temporário e se recusou a honrar minha 'byref'. Acontecia a cada três anos, aproximadamente o tempo que levava para esquecer o último incidente.
FastAl
16

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")
ricos
fonte
Uau, isso é super legal! Vi isso ao usar serviços da Web etc., mas não sabia que você poderia fazer isso de qualquer método normal.
RichC 22/12/08
2
Definitivamente, uma ferramenta muito útil quando você encontra um método que requer muitos argumentos. Tento nomear cada parâmetro e colocar o nome: = value em sua própria linha. É muito mais intuitivo e limpo para métodos que usam parâmetros> 5 (minha regra de ouro).
STW
Especialmente útil para automação do Office, onde você precisa lidar com métodos com dezenas de argumentos opcionais.
9139 MarkJ às
1
O que também é legal é que você pode misturar os dois: comece especificando os parâmetros necessários em ordem e depois mude para parâmetros nomeados para os argumentos opcionais!
RBarryYoung 19/09/09
15

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
histórico
fonte
23
Vale a pena notar (apenas porque esqueci pelo menos duas vezes) que você pode fazer com que uma instrução Using use vários objetos descartáveis. A sintaxe é "Usando objA como novo objeto, objB como novo objeto ..." É muito mais limpo do que aninhar várias instruções Using.
STW
Definitivamente um dos meus favoritos também.
21339 Sam Ax
14

Os aliases de importação também são amplamente desconhecidos:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form
histórico
fonte
1
Eu acho que tivemos a mesma ideia.
Chrissie1
3
@ Boo - aqui está um exemplo simples, onde aliases de importação não são maus. stackoverflow.com/questions/92869/…
torial
Ok - existe uma avenida óbvia para abuso, mas, independentemente do discurso retórico do @ torial, esse é um ótimo recurso. Sempre que incluo System.Text.RegularExpressions, arrisco-me a ter colisões de nomes com a classe "Group", pois esse é um nome de classe comum. O alias permite evitar a qualificação completa de classes ambíguas, o que economiza muito tempo e aprimora a legibilidade quando usado corretamente. O recurso é excelente, mas seu exemplo específico meio que convida a um ridículo - lamento dizer.
mattmc3
14

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

Jargão técnico incompreensível
fonte
Por que você iria querer fazer isso? Não consigo imaginar um caso de uso em que você precise saber o número de inscritos em um evento no VB.
319 Konrad Rudolph
Em certas circunstâncias, o C # lança uma exceção se você aumentar o evento e não houver manipuladores. VB.Net não. Daí a necessidade de verificar.
Joel Coehoorn
2
Eu usei isso para um evento de objeto de negócios que gerou mensagens de erro de validação para os assinantes. Eu queria verificar se o evento estava sendo tratado para saber que os erros de validação estavam sendo recebidos. Caso contrário, o objeto de negócios lançaria uma exceção.
Technobabble 18/11/08
2
Outro uso útil para esse membro privado é obter a lista de chamadas do evento. Eu o usei em vários casos para disparar o evento de maneira assíncrona para todos os chamadores (impede o Ouvinte A de modificar o evento antes do Ouvinte B recebê-lo; também impede o Ouvinte A de atrasar a entrega ao Ouvinte B). Eu usei muito isso em cenários personalizados de sincronização de dados e também em APIs.
STW
14

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
histórico
fonte
Eu acho que esse exemplo seria melhor se você não usasse "If" como palavra-chave de exemplo.
21768 Sean Gough
4
timer.Start e primavera timer.Stop à mente como exemplos de bom uso deste
Pondidum
5
+1 por apontar com um aviso de isenção de responsabilidade. Existem várias classes de estrutura que exigem este para resolver corretamente, como [Assembléia]
STW
5
[Enum] é outro bom exemplo de caso em que você precisa dos colchetes para usar a classe em vez da palavra-chave.
Ryan Lundy
13

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.)

Ryan Lundy
fonte
3
<q>seria uma boa tag, semelhante ao uso em Perl / Ruby. Enfim, essa é uma linguagem legal. GOSTAR!
Konrad Rudolph
Que ideia genial. Obrigado
Jeremy
12

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)
danlash
fonte
6
Não se você tiver a opção Strict On
ativada
12

Você pode ter 2 linhas de código em apenas uma linha. conseqüentemente:

Dim x As New Something : x.CallAMethod
Parsa
fonte
Uau ... eu pensei que isso só foi possível w / classe e herança
Jason
Não se esqueça deCall (New Something).CallAMethod()
Jonathan Allen
Este é um recurso do MS-Basic na Apple] [! Na minha loja, eu seria tão ridicularizado por usar o Gotos: - /
FastAl
Na maioria das vezes, isso deve ser evitado, mas onde eu gosto de usá-lo é nas declarações de casos em que as linhas são realmente curtas, por exemplo, Caso 4: x = 22
dwidel 30/12/2010
11

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
dr. mal
fonte
1
Eu não sabia que o C # iria pegá-los. Eles são legais, mas você deve ter cuidado para usá-los somente quando tiver certeza de que o código não será consumido pelo C #, pois não os suporta. O FxCop / Code Analysis solicitará que você sobrecarregue o método.
STW
... Acabei de encontrar um ótimo uso para os parâmetros opcionais, mantendo-os fora do código de produção. Escrevi-up um curto post sobre isso no meu site: yoooder.com/wordpress/?p=62
STW
2
Ah, eu desprezo esse tanto ... Mas útil para automação de escritório
dance2die
9

O Case Title no VB.Net pode ser obtido por um antigo VB6 fxn:

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
histórico
fonte
1
também está na classe textinfo. não sei o namespace que está em provavelmente System.Text.
Shawn
É melhor que você seja neutro no idioma .net e use a classe Globalization TextInfo para converter ToTitleCase. Se você código nunca precisa ser convertido em C # você terá lotes de pequenas sujeiras que requerem Microsoft.VisualBasic
Jeremy
9

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
torial
fonte
Isso é interessante, mas não tenho certeza de onde isso seria útil. myObj.Something ("abc") parece mais que você está acessando uma Função do que uma propriedade. Não tenho certeza do que isso compra.
mattmc3
Eu odeio ambiguidade. O que deveria ser. Um método ou uma propriedade. Algumas ferramentas de refatoração sugerem a criação de ambos em determinadas situações também, parece que eles não sei mesmo ...
brumScouse