Funzionalità nascoste di VB.NET?


121

Ho imparato un bel po 'sfogliando le funzionalità nascoste di C # e sono rimasto sorpreso quando non sono riuscito a trovare qualcosa di simile per VB.NET.

Quindi quali sono alcune delle sue caratteristiche nascoste o meno conosciute?

Risposte:


128

La Exception Whenclausola è in gran parte sconosciuta.

Considera questo:

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

9
utile se desideri catturare una SQLException specifica, dì -2 che se ricordo correttamente è il timeout di rete: Catch ex as sqlException dove ex.code = -2
Pondidum

Wow! L'ho appena letto e l'ho utilizzato immediatamente per semplificare un blocco try / catch che ho scritto la scorsa settimana. Non ho mai saputo che questo esistesse.
John M Gant

1
1 E qui è dove il NET blog del team CLR spiega perché i filtri di eccezione sono utili blogs.msdn.com/clrteam/archive/2009/02/05/...
MarkJ

5
Non solo è nascosto, ma non è disponibile in C #.
Cheeso

82

Personalizzato Enums

Una delle vere caratteristiche nascoste di VB è il completionlisttag di documentazione XML che può essere utilizzato per creare Enumtipi propri con funzionalità estese. Tuttavia, questa funzionalità non funziona in C #.

Un esempio da un mio codice recente:

'
''' <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

Ora, quando si assegna un valore a una variabile dichiarata come Rule, l'IDE offre un elenco IntelliSense di possibili valori da RuleTemplates.

/MODIFICARE:

Poiché questa è una funzionalità che si basa sull'IDE, è difficile mostrare come appare quando la usi, ma userò solo uno screenshot:

Elenco di completamento in azione http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png

In effetti, IntelliSense è identico al 100% a quello che ottieni quando usi un file Enum.


Interessante: potresti mostrare un esempio di come appare quando lo consumi?
Brian MacKay

Sembra che qualcuno possa ancora creare la propria regola chiamando direttamente il costruttore di regole? Se è così, e se volessi fermarlo, potresti dichiarare il costruttore come "Amico" nella tua libreria?
Joel Coehoorn

Joel, nel mio codice di esempio non l'ho intenzionalmente proibito. Piuttosto, offro all'utente alcune regole comuni e consento la creazione di regole proprie e specializzate. Ovviamente puoi impedirlo contrassegnando il costruttore come friendo usando la stessa classe dell'enum: Ruleinvece di RuleTemplate.
Konrad Rudolph

c'è da qualche parte un elenco di usi di attributi utili nascosti? questo in apparenza sembra incredibile, ma non sono ancora sicuro di dove lo userei o se potesse risolvere un problema principale in alcuni casi senza la possibilità di avere un generico limitato agli enumerativi.
Maslow

@ Maslow: non ci sono attributi coinvolti qui. Questo è un commento xml.
Joel Coehoorn

49

Hai notato l'operatore di confronto Like?

Dim b As Boolean = "file.txt" Like "*.txt"

Altro da 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*"

3
aspetta cosa? È nuovo per me! Hmm, è molto meglio dell'alternativa con la manipolazione delle stringhe VB.NET: D
STW

.. !! Non lo sapevo, sebbene lavorassi a diversi progetti vb.net! Funzionalità interessante ...
Meta-Knight

woooooooooooooooooooooooow! Grazie! è stupendo! funziona anche in ELinq, DLinq? che dire di XLinq?
Shimmy Weitzhandler

@dotjoe Hmm? Non c'è niente di "pigro" in questi globi.
Josh Lee,

Come funziona, cosa sta succedendo sotto il cofano? È sinonimo di reg ex librerie?
brumScouse

48

typedef

VB conosce un tipo primitivo di alias typedefvia Import:

Imports S = System.String

Dim x As S = "Hello"

Questo è più utile se usato insieme a tipi generici:

Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)

2
per favore mostra un esempio la parola Import non è riconosciuta nel mio IDE.
Shimmy Weitzhandler

5
Importsdovrebbe essere. ;-) In qualche modo, questo errore è passato inosservato (e ha ottenuto 28 voti positivi) per quasi un anno intero.
Konrad Rudolph

Mi sono sempre chiesto come avrei potuto creare un nuovo "tipo" con valori predefiniti per un generico! Freddo!
eidylon

3
Importa, importa, importa, qualunque cosa! Sheesh, pensi che abbiamo letto questi post prima di votarli!
MarkJ

Eccellente per l'utilizzo di xunit nei test in studio visivo, ad esempioImports Assert = xUnit.Assert
wheelibin

45

Oh! e non dimenticare i letterali XML .

Dim contact2 = _
        <contact>
          <name>Patrick Hines</name>
          <%= From p In phoneNumbers2 _
            Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
          %>
        </contact>

Questo è quello che stavo per dire. In effetti, ho usato letterali XML per uno scopo in cui non era previsto. L'ho usato per produrre Javascript ... swortham.blogspot.com/2009/03/vb-2008.html
Steve Wortham

9
Tra le altre cose, puoi usare XML Literals per aggirare il brutto escape delle stringhe, ad esempio quando stai usando stringhe che contengono a loro volta virgolette doppie. Basta mettere la stringa all'interno di un letterale XML e chiamare valore, in questo modo: <string>This string contains "quotes" and it's OK.</string>.Value (Ho trovato questo particolarmente utile durante la scrittura di test su parsing file CSV in cui ogni campo è stato tra virgolette Sarebbe. Non stato divertente per sfuggire tutte quelle citazioni a mano nel mio linee di prova.)
Ryan Lundy

2
@Kyralessa: +1, ottimo commento. In effetti, è anche un ottimo modo per specificare stringhe su più righe (abbraccia le istruzioni SQL, ecc.).
Heinzi

Inline XML è una delle peggiori funzionalità di VB.NET mai concepite. Fatto infondato.
Grant Thomas

39

C'è anche l'inizializzazione degli oggetti!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}

1
Non posso credere che siano andati con le parentesi graffe. Abbiamo già un'istruzione With .. avrebbero potuto semplicemente riutilizzare quella sintassi.
Sam Axe

2
Lo so, è fatto solo per dimostrarti che non c'è nessun poliziotto per strada ... lol JK
Shimmy Weitzhandler

4
Questo è ciò che accade quando tutti gli autori di compilatori sono essi stessi programmatori C / C ++ nel cuore. Continuano a far scivolare la sintassi C in altri linguaggi perché non riescono a concepire che nulla sia migliore.
RBarryYoung

38

DirectCast

DirectCastè una meraviglia. In superficie, funziona in modo simile CTypeall'operatore in quanto converte un oggetto da un tipo a un altro. Tuttavia, funziona secondo una serie di regole molto più rigide. CTypeL'effettivo comportamento è quindi spesso opaco e non è affatto evidente quale tipo di conversione viene eseguita.

DirectCast supporta solo due operazioni distinte:

  • Unboxing di un tipo di valore e
  • upcasting nella gerarchia di classe.

Qualsiasi altro cast non funzionerà (ad esempio, tentando di decomprimere un Integerin a Double) e risulterà in un errore in fase di compilazione / runtime (a seconda della situazione e di ciò che può essere rilevato dal controllo del tipo statico). Pertanto lo uso DirectCastogni volta che è possibile, poiché questo cattura al meglio il mio intento: a seconda della situazione, desidero estrarre un valore di tipo noto o eseguire un upcast. Fine della storia.

L'utilizzo CType, d'altra parte, lascia il lettore del codice a chiedersi cosa intendesse veramente il programmatore perché risolve tutti i tipi di operazioni diverse, inclusa la chiamata di codice definito dall'utente.

Perché questa è una caratteristica nascosta? Il team di VB ha pubblicato una linea guida 1 che ne scoraggia l'uso DirectCast(anche se in realtà è più veloce!) Per rendere il codice più uniforme. Ritengo che questa sia una cattiva linea guida che dovrebbe essere invertita: quando possibile, favorisci DirectCastl' CTypeoperatore più generale . Rende il codice molto più chiaro. CType, d'altra parte, dovrebbe essere chiamato solo se questo è davvero inteso, cioè quando dovrebbe essere chiamato un CTypeoperatore di restringimento (cfr. sovraccarico di operatori ).


1) Non riesco a trovare un collegamento alla linea guida ma ho trovato l' opinione di Paul Vick (capo sviluppatore del team VB):

Nel mondo reale, non noterai quasi mai la differenza, quindi potresti anche optare per operatori di conversione più flessibili come CType, CInt, ecc.


(EDIT by Zack: Ulteriori informazioni qui: come devo eseguire il cast in VB.NET? )


In realtà mi piace TryCast () un po 'di più. Non genererà un'eccezione, restituirà semplicemente Nothing se il cast fallisce. Se ti aspetti che il cast fallisca spesso, è più veloce di If TypeOf x Is T ... DirectCast (x, T) e sicuramente più veloce di catturare l'eccezione se DirectCast fallisce.
Bob King,

6
DirectCast () e TryCast () sono inestimabili se utilizzati correttamente in coppia. DirectCast () dovrebbe essere utilizzato se si prevede che l'oggetto di cui si esegue il cast sia sempre il tipo di destinazione (in caso contrario, verrà visualizzato un errore, una buona cosa poiché si tratta di una situazione imprevista). TryCast () dovrebbe essere utilizzato se l'oggetto che viene lanciato potrebbe essere del tipo di destinazione o di diversi tipi di destinazione. L'uso esclusivo dell'uno o dell'altro porterà a un sovraccarico extra (se typeof x è y allora directcast (x, y) è inefficiente) o ad evitare errori validi (usando TryCast () per i casi in cui l'oggetto dovrebbe sempre essere il tipo di destinazione)
STW

Yoooder: corretto al 100%. È un peccato non averlo menzionato TryCastallora poiché avevo principalmente un osso da scegliere con l'uso pervasivo CType.
Konrad Rudolph

@ Maslow: ovviamente no, dal momento che gli Enum sono tipi di valore e TryCastfunzionano solo sui tipi di riferimento, come da documentazione.
Konrad Rudolph,

+1: Heh. Devo ammetterlo, ho appena letto questo e ho pensato "Oh sì, DirectCast, come ho fatto a dimenticarmene?" E poi l'ho usato sulla mia prossima riga di codice (dato che non mi piace davvero CType).
RBarryYoung

37

If operatore condizionale e coalesce

Non so come lo chiameresti nascosto, ma la funzione Iif ([espressione], [valore se vero], [valore se falso]) As Oggetto potrebbe contare.

Non è tanto nascosto quanto deprecato ! VB 9 ha l' Ifoperatore che è molto migliore e funziona esattamente come l'operatore condizionale e coalesce di C # (a seconda di ciò che si desidera):

Dim x = If(a = b, c, d)

Dim hello As String = Nothing
Dim y = If(hello, "World")

Modificato per mostrare un altro esempio:

Funzionerà con If(), ma causerà un'eccezione conIIf()

Dim x = If(b<>0,a/b,0)

Bello, non lo sapevo! Ho appena usato IIF ieri, quindi rivisiterò quel blocco di codice.
Sean Gough

4
Ditelo a VS 2005. Non tutti noi lavoriamo con le ultime novità.
Sam Erwin

3
@Slough, nonsense. Questo metodo è sicuro al 100% e restituisce un oggetto dello stesso tipo del suo (secondo e terzo) argomento. Inoltre, deve esserci una conversione più ampia tra gli argomenti, altrimenti ci sarà un errore di compilazione perché i tipi non corrispondono.
Konrad Rudolph,

1
Sì, è IIf () che non è indipendente dai tipi
Pondidum

2
@ Br.Bill In effetti, è completamente equivalente a C e l' :?operatore di Perl , non è solo una versione semplificata.
Konrad Rudolph

32

Questo è carino. L'istruzione Select Case all'interno di VB.Net è molto potente.

Certo che c'è lo standard

Select Case Role
  Case "Admin"
         ''//Do X
  Case "Tester"
         ''//Do Y
  Case "Developer"
         ''//Do Z
  Case Else
       ''//Exception case
End Select

Ma c'è di più ...

Puoi fare intervalli:

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 anche di più...

Puoi (anche se potrebbe non essere una buona idea) eseguire controlli booleani su più variabili:

Select Case True
 Case a = b
    ''//Do X
 Case a = c
    ''//Do Y
 Case b = c
    ''//Do Z
 Case Else
   ''//Exception case
 End Select

5
In realtà ti sei perso un paio: a) l'uso di "Select Case True" per testare più di una variabile, b) l'uso del modulo "Case A, B, ...", e anche c) applicare il ":" a riga l'istruzione di esecuzione con la clausola condition (anche se a molti non piace).
RBarryYoung

6
Non utilizzare Seleziona maiuscole e minuscole. Usa semplicemente un'istruzione If.
Ryan Lundy

4
Trovo Select Case True molto più facile da leggere di una gigantesca dichiarazione ifelse.
dwidel

Il problema Select Case Trueè che sembra che valuti ciascuna delle Caseaffermazioni ed esegua il codice per ognuna che è vera. Ma in realtà li valuta uno per uno e esegue il codice solo per il primo che è vero. La sintassi per Ifè molto più chiara a questo proposito ( If...Else If...Else If...Else).
Ryan Lundy

31

Un importante risparmio di tempo che uso sempre è la parola chiave With :

With ReallyLongClassName
    .Property1 = Value1
    .Property2 = Value2
    ...
End With

Semplicemente non mi piace scrivere più di quanto devo!


Ma crea anche alcuni bug nascosti, specialmente quando hai Con dentro Con
Varun Mahajan

2
Non sapevo nemmeno che potessi inserire un nuovo With all'interno di un With esistente. È solo sciatto!
Bob King,

2Bob: non è sciatto, suggerirei .. è solo un costrutto di linguaggio da usare con cura. Per impostare molte proprietà in righe successive, è fantastico, ma trovare un .Foo casuale in un pezzo di codice complesso e quindi dover cercare le righe x dell'istruzione With sopra non è un buon uso della funzionalità.
ChrisA

2
Desideri che C # abbia questo? O sono stato addormentato ed è già nelle risposte di funzionalità nascoste C # ...? ;-)
peSHIr

1
@ Boo: hai ragione, ma è comunque un fastidio non poterlo aggiungere alla Watch list.
Meta-Knight

31

Il migliore e facile parser CSV:

Microsoft.VisualBasic.FileIO.TextFieldParser

Aggiungendo un riferimento a Microsoft.VisualBasic, questo può essere utilizzato in qualsiasi altro linguaggio .Net, ad esempio C #


5
+1 È strano come le persone di C # corrono su FileHelpers senza mai considerarlo. Sono sicuro che FileHelpers è eccellente, ma è una dipendenza esterna.
MarkJ

@MarkJ Presumo sia a causa dell'ignoranza
Nathan Koop,

Ho cercato su Google di trovare questa classe e non l'ho mai fatto, grazie per averla segnalata!
pingoo


25

Membri statici nei metodi.

Per esempio:

Function CleanString(byval input As String) As String
    Static pattern As New RegEx("...")

    return pattern.Replace(input, "")
End Function

Nella funzione precedente, l'espressione regolare del modello verrà creata solo una volta, indipendentemente da quante volte viene chiamata la funzione.

Un altro utilizzo è mantenere un'istanza di "random" in giro:

Function GetNextRandom() As Integer
    Static r As New Random(getSeed())

    Return r.Next()
End Function 

Inoltre, questo non è la stessa cosa che dichiararlo semplicemente come membro condiviso della classe; gli elementi dichiarati in questo modo sono garantiti anche thread-safe. Non importa in questo scenario poiché l'espressione non cambierà mai, ma ce ne sono altre in cui potrebbe.


1
Un utilizzo di questo è mantenere un contatore che aumenterà ogni volta che viene chiamato il metodo. Se la variabile è contrassegnata come Static, non verrà reinizializzata ad ogni chiamata al metodo; verrà inizializzato solo alla prima chiamata e successivamente manterrà il suo valore.
Ryan Lundy

Questo è il motivo per cui i membri della classe statica sono denominati "condivisi" in VB.NET
Enrico Campidoglio

Lo statico è una cattiva forma in VB.NET anche più di quanto non fosse nel classico VB. Le variabili statiche dovrebbero essere evitate quando e dove possibile.
Sam Axe

6
@Boo - è abbastanza radicale. Qual è la tua giustificazione? Penso che le variabili statiche siano utili.
MarkJ

4
Statico, utilizzato come negli esempi precedenti, consente una forma unica di incapsulamento: variabili a livello di classe con ambito a livello di metodo. Senza di essa, dovresti creare una variabile a livello di classe che sarebbe accessibile a qualsiasi membro della classe, anche se la stai utilizzando solo in un metodo.
Ryan Lundy

25

In vb c'è una differenza tra questi operatori:

/si Double
\è Integerignorando il resto

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

1
L'ho imparato nel modo più duro cercando di trovare un ago in un milione di righe di codice. divisione regolare contro intera. Bel consiglio!
Jason Irwin,

23

Mi piace molto lo spazio dei nomi "My" che è stato introdotto in Visual Basic 2005. My è un collegamento a diversi gruppi di informazioni e funzionalità. Fornisce un accesso rapido e intuitivo ai seguenti tipi di informazioni:

  • My.Computer : accesso alle informazioni relative al computer come file system, rete, dispositivi, informazioni di sistema, ecc. Fornisce accesso a una serie di risorse molto importanti tra cui My.Computer.Network, My.Computer.FileSystem e My .Computer.Printers.
  • My.Application : accesso alle informazioni relative alla particolare applicazione come nome, versione, directory corrente, ecc.
  • My.User : accesso alle informazioni relative all'utente corrente autenticato.
  • My.Resources : L'accesso alle risorse utilizzate dall'applicazione residente in file di risorse in un modo fortemente tipizzato.
  • Impostazioni personali : accesso alle impostazioni di configurazione dell'applicazione in modo fortemente digitato.

Questo è semplicemente fantastico e ogni ragazzo di vb.net là fuori dovrebbe sapere cose nel mio spazio dei nomi, è così utile.
dott. il male

Il mio. * FTW :).
dott. il male

3
È un po 'utile, ma odio il nome stupido. Mi ricorda di questo secretgeek.net/refactvb.asp
MarkJ

23

Eventi personalizzati

Sebbene raramente utile, la gestione degli eventi può essere fortemente personalizzata:

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

Questo può quindi essere testato nel modo seguente:

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

sembra bello, ma se mai ne avessi bisogno penso che avrei fatto qualcosa di sbagliato ;-). Sembra solo contro il principio KISS.
chrissie1

4
È davvero molto utile quando vuoi assicurarti che ogni sink riceva l'evento anche se uno o più generano un'eccezione.
Jonathan Allen

Un altro valore (l'ho appena letto sul sito MSDN) è che se la tua classe genera molti eventi, puoi costringerla a utilizzare una tabella / dizionario hash come contenitore, invece di dichiarare un campo per ogni evento. msdn.microsoft.com/en-us/library/8627sbea(VS.71).aspx
torial

Freddo. Ho pensato che questa fosse una delle caratteristiche che distinguono C # e VB.NET (come in uno può, ma nell'altro non ha sintassi). Bello almeno sapere che mi sbagliavo sotto questo aspetto.
peSHIr

21

Ho appena trovato un articolo che parla del "!" operatore, noto anche come "operatore di ricerca nel dizionario". Ecco un estratto dell'articolo su: http://panopticoncentral.net/articles/902.aspx

Il nome tecnico per il! operatore è l '"operatore di ricerca nel dizionario". Un dizionario è un tipo di raccolta indicizzato da una chiave anziché da un numero, proprio come le voci di un dizionario inglese sono indicizzate dalla parola di cui si desidera la definizione. L'esempio più comune di un tipo di dizionario è System.Collections.Hashtable, che consente di aggiungere coppie (chiave, valore) nella tabella hash e quindi recuperare i valori utilizzando le chiavi. Ad esempio, il codice seguente aggiunge tre voci a una tabella hash e ne cerca una utilizzando la chiave "Pork".

Dim Table As Hashtable = New Hashtable
Table("Orange") = "A fruit"
Table("Broccoli") = "A vegetable"
Table("Pork") = "A meat" 
Console.WriteLine(Table("Pork"))

Il ! L'operatore può essere utilizzato per cercare i valori da qualsiasi tipo di dizionario che ne indicizza i valori utilizzando le stringhe. L'identificatore dopo il! viene utilizzato come chiave nell'operazione di ricerca. Quindi il codice sopra potrebbe invece essere stato scritto:

Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)

Il secondo esempio è completamente equivalente al primo, ma sembra molto più carino, almeno ai miei occhi. Trovo che ci siano molti posti dove! può essere utilizzato, soprattutto quando si tratta di XML e web, dove ci sono solo tonnellate di raccolte indicizzate per stringa. Una sfortunata limitazione è che la cosa che segue! deve ancora essere un identificatore valido, quindi se la stringa che vuoi usare come chiave contiene un carattere identificativo non valido, non puoi usare il! operatore. (Non puoi, ad esempio, dire "Tabella! AB $ CD = 5" perché $ non è legale negli identificatori.) In VB6 e versioni precedenti, potresti usare le parentesi per sfuggire agli identificatori non validi (ad esempio "Tabella! [AB $ CD] "), ma quando abbiamo iniziato a utilizzare le parentesi per sfuggire alle parole chiave, abbiamo perso la capacità di farlo. Nella maggior parte dei casi,

Per essere davvero tecnici, x! Y funziona se x ha una proprietà predefinita che accetta una stringa o un oggetto come parametro. In tal caso, x! Y viene modificato in x.DefaultProperty ("y"). Una nota a margine interessante è che c'è una regola speciale nella grammatica lessicale della lingua per far funzionare tutto questo. Il ! Il carattere viene utilizzato anche come carattere di tipo nella lingua e i caratteri di tipo vengono mangiati prima degli operatori. Quindi, senza una regola speciale, x! Y verrebbe scansionato come "x! Y" invece di "x! Y". Fortunatamente, poiché non c'è posto nella lingua in cui due identificatori di fila siano validi, abbiamo appena introdotto la regola che se il carattere successivo dopo! è l'inizio di un identificatore, consideriamo il! essere un operatore e non un carattere di tipo.


11
Questa è una di quelle funzionalità che ho usato e poi ho intenzionalmente dimenticato. Salva alcuni tasti premuti ma crea problemi con l'evidenziazione e la leggibilità del codice. dimenticare di nuovo a destra .... NOW
STW

3
Interessante, ma non proprio utile. È questo il tipo di cose su cui lavora il team VB invece di aggiungere funzionalità mancanti come la parola chiave yield? : P
Meta-Knight

5
Questa funzione viene utilizzata per compatibilità con le versioni precedenti da VB3 (AFAIK)
Eduardo Molteni

1
quelle classi che implementano un indice con chiave hanno un'interfaccia comune da cui ereditano? come IKeyed allo stesso modo i contenitori indicizzati interi implementano IENumberable?
Maslow,

2
Questa funzione funziona anche con DataRows (cioè dr! ID) che è MOLTO utile in LINQ to DataSets.
Paul

19

Questo è integrato e rappresenta un netto vantaggio rispetto a C #. La possibilità di implementare un metodo di interfaccia senza dover utilizzare lo stesso nome.

Ad esempio:

Public Sub GetISCSIAdmInfo(ByRef xDoc As System.Xml.XmlDocument) Implements IUnix.GetISCSIInfo

End Sub

Sono sicuro che puoi fare qualcosa di simile in C #. In VB.NET è solo forzato, e in C # è opzionale?
Jesper Blad Jensen

5
Puoi anche rendere privato il sub, che è un ottimo modo per nascondere cose come le chiamate a versioni deprecate di interfacce non generiche.
Craig Gidney,

3
Può essere una buona idea. L'esempio classico sarebbe se si desidera un metodo Public Close che funga anche da implementazione Dispose per IDisposable.
MarkJ

1
È anche molto utile se ti capita di implementare due interfacce che condividono un nome di metodo.
Eric Nicholson

L'ho visto e avrei sempre voluto non averlo visto. Non dovrebbe essere consentito.
FastAl

17

Forzare ByVal

In VB, se racchiudi i tuoi argomenti in un set aggiuntivo di parentesi, puoi sovrascrivere la dichiarazione ByRef del metodo e trasformarla in ByVal. Ad esempio, il codice seguente produce 4, 5, 5 invece di 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

Vedere Argomento non modificato dalla chiamata di procedura - Variabile sottostante


6
Oh mio Dio ... questa è una caratteristica notevole, anche se non credo che saprei cosa stava facendo se la leggessi nel codice di qualcun altro. Se devi commentarlo solo per sapere cosa sta facendo, potresti anche aver fatto passare la variabile di eliminazione.
mattmc3

7
Questo è in realtà un effetto collaterale dell'uso delle parentesi: le parentesi creano un valore temporaneo di ciò che è all'interno, anche se solo un elemento. Questo effetto MI HA UCCISO in vb6 - Le chiamate secondarie non hanno preso i genitori, ma io proveniente da C ho istintivamente inserito le parentesi. 6.0 è esploso su più parametri, ma per i sottotitoli di un parametro, ha felicemente passato un valore temporaneo e RIFIUTATO per onorare il mio 'byref'. Succedeva circa ogni 3 anni, più o meno il tempo che mi ci è voluto per dimenticare l'ultimo incidente.
FastAl

16

Passare i parametri per nome e, quindi, riordinarli

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

Può anche essere chiamato utilizzando la specifica del parametro ": =" in qualsiasi ordine:

MyFunc(displayOrder:=10, msg:="mystring")

Wow, è fantastico! L'ho visto usando i servizi Web, ecc., Ma non sapevo che potessi farlo con un qualsiasi metodo normale.
RichC

2
Sicuramente uno strumento molto utile quando si incontra un metodo che richiede troppi argomenti. Provo a nominare ogni parametro e metto il nome: = valore su una riga separata. È molto più intuitivo e pulito per i metodi che accettano> 5 (la mia regola pratica) parametri.
STW

Particolarmente utile per l'automazione di Office, dove devi affrontare metodi con dozzine di argomenti opzionali.
MarkJ

1
La cosa interessante è che puoi mescolare i due: inizia specificando i parametri richiesti in ordine, quindi passa ai parametri con nome per gli argomenti opzionali!
RBarryYoung

15

L'istruzione Using è nuova a partire da VB 8, C # l'aveva dall'inizio. Chiama dispose automagicamente per te.

Per esempio

Using lockThis as New MyLocker(objToLock)

End Using

23
Vale la pena notare (solo perché ho dimenticato almeno due volte) che puoi avere un'istruzione Using che racchiude diversi oggetti usa e getta. La sintassi è "Uso di objA come nuovo oggetto, objB come nuovo oggetto ..." È molto più chiara rispetto all'annidamento di più istruzioni Using.
STW

Sicuramente anche uno dei miei preferiti.
Sam Axe

14

Anche gli alias di importazione sono in gran parte sconosciuti:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form

1
Penso che abbiamo avuto la stessa idea.
chrissie1

3
@Boo - ecco un semplice esempio in cui gli alias di importazione non sono malvagi. stackoverflow.com/questions/92869/…
torial

Ok, c'è una via ovvia per gli abusi, ma indipendentemente dallo sfogo di @ torial questa è una grande caratteristica. Ogni volta che includo System.Text.RegularExpressions rischio di avere conflitti di nome con la classe "Group" poiché è un nome di classe comune. L'alias ti consente di evitare di dover qualificare completamente le classi ambigue, il che è un enorme risparmio di tempo e migliora effettivamente la leggibilità se usato correttamente. La funzione è fantastica, ma il tuo esempio specifico in qualche modo invita al ridicolo, mi dispiace dirlo.
mattmc3

14

Considera la seguente dichiarazione di evento

Public Event SomethingHappened As EventHandler

In C # è possibile verificare la presenza di sottoscrittori di eventi utilizzando la sintassi seguente:

if(SomethingHappened != null)
{
  ...
}

Tuttavia, il compilatore VB.NET non lo supporta. In realtà crea un campo membro privato nascosto che non è visibile in IntelliSense:

If Not SomethingHappenedEvent Is Nothing OrElse SomethingHappenedEvent.GetInvocationList.Length = 0 Then
...
End If

Maggiori informazioni:

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


Perché mai avresti voluto farlo? Non riesco a immaginare un caso d'uso in cui è necessario conoscere il numero di abbonati a un evento in VB.
Konrad Rudolph

In alcune circostanze, C # genera un'eccezione se si genera l'evento e non sono presenti gestori. VB.Net non lo farà. Da qui la necessità di verificare.
Joel Coehoorn

2
L'ho usato per un evento dell'oggetto di business che ha generato messaggi di errore di convalida agli abbonati. Volevo controllare se l'evento era stato gestito in modo da sapere che gli errori di convalida venivano ricevuti. In caso contrario, l'oggetto business ha generato un'eccezione.
Technobabble

2
Un altro utile utilizzo per questo membro privato è ottenere l'elenco delle chiamate dell'evento. L'ho utilizzato in diversi casi per attivare l'evento in modo asincrono a tutti i chiamanti (impedisce al listener A di modificare l'evento prima che il listener B lo riceva; inoltre impedisce al listener A di ritardare la consegna al listener B). L'ho usato molto negli scenari di sincronizzazione dei dati personalizzati e anche nelle API.
STW

14

Se hai bisogno di un nome di variabile che corrisponda a quello di una parola chiave, racchiudilo tra parentesi. Non nca. la migliore pratica, tuttavia, ma può essere utilizzata con saggezza.

per esempio

Class CodeException
Public [Error] as String
''...
End Class

''later
Dim e as new CodeException
e.Error = "Invalid Syntax"

ad es. Esempio dai commenti (@Pondidum):

Class Timer
Public Sub Start()
''...
End Sub

Public Sub [Stop]()
''...
End Sub

Penso che questo esempio sarebbe migliore se non usassi "If" come parola chiave di esempio.
Sean Gough

4
timer.Start e timer.Stop mi vengono in mente come esempi di buon uso di questo
Pondidum

5
+1 per averlo segnalato con un disclaimer. Esistono diverse classi di framework che richiedono che ciò venga risolto correttamente, come [Assembly]
STW

5
[Enum] è un altro buon esempio di un caso in cui sono necessarie le parentesi per utilizzare la classe invece della parola chiave.
Ryan Lundy

13

Ci sono un paio di risposte sui valori letterali XML, ma non su questo caso specifico:

È possibile utilizzare valori letterali XML per racchiudere valori letterali stringa che altrimenti dovrebbero essere sottoposti a escape. Valori letterali stringa che contengono virgolette doppie, ad esempio.

Invece di questo:

Dim myString = _
    "This string contains ""quotes"" and they're ugly."

Puoi farlo:

Dim myString = _
    <string>This string contains "quotes" and they're nice.</string>.Value

Ciò è particolarmente utile se stai testando un letterale per l'analisi CSV:

Dim csvTestYuck = _
    """Smith"", ""Bob"", ""123 Anywhere St"", ""Los Angeles"", ""CA"""

Dim csvTestMuchBetter = _
    <string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value

(Non devi usare il <string>tag, ovviamente; puoi usare qualsiasi tag che ti piace.)


3
<q>sarebbe un buon tag, simile all'uso in Perl / Ruby. Comunque, è un bel modo di dire. PIACE!
Konrad Rudolph

Che idea geniale. Grazie
Jeremy

12

DateTime può essere inizializzato circondando la data con #

Dim independanceDay As DateTime = #7/4/1776#

Puoi anche usare l'inferenza del tipo insieme a questa sintassi

Dim independanceDay = #7/4/1776#

È molto più bello che usare il costruttore

Dim independanceDay as DateTime = New DateTime(1776, 7, 4)

6
No se hai Option Strict On
danlash

12

Puoi avere 2 righe di codice in una sola riga. quindi:

Dim x As New Something : x.CallAMethod

whoa ... pensavo fosse possibile solo con classe ed eredità
Jason

Non dimenticareCall (New Something).CallAMethod()
Jonathan Allen

Questo è un holdever di MS-Basic su Apple] [! Nel mio negozio sarei altrettanto ridicolizzato per aver usato Gotos: - /
FastAl

Il più delle volte questo deve essere evitato, ma dove mi piace usarlo è nelle istruzioni case in cui le linee sono davvero brevi, ad esempio Case 4: x = 22
dwidel

11

Parametri opzionali

Gli optionals sono molto più facili rispetto alla creazione di nuovi overload, come ad esempio:

Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
   Console.Writeline(msg)
   ''//do stuff
End Function

1
Non sapevo che C # li avrebbe acquisiti. Sono carini, ma devi stare attento a usarli solo dove sei sicuro che il codice non verrà consumato da C # poiché non li supporta. FxCop / Code Analysis ti dirà invece di sovraccaricare il metodo.
STW

... Ho appena trovato un ottimo utilizzo per i parametri opzionali, pur mantenendoli fuori dal codice di produzione. Ho scritto un breve post al riguardo sul mio sito: yoooder.com/wordpress/?p=62
STW

2
Ah, lo disprezzo così tanto ... Ma utile per l'automazione dell'ufficio
dance2die

9

Il caso del titolo in VB.Net può essere ottenuto da un vecchio fxn VB6:

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID

1
è anche nella classe textinfo. non sono sicuro di quale spazio dei nomi si trovi. probabilmente system.text
Shawn

È meglio essere neutrali rispetto al linguaggio .net e utilizzare la classe Globalization TextInfo per convertire ToTitleCase. Se il codice deve essere convertito in C #, avrai un sacco di piccoli cattivi che richiedono Microsoft.VisualBasic
Jeremy,

9

Proprietà con parametri

Ho fatto un po 'di programmazione C # e ho scoperto una funzionalità che mancava che VB.Net aveva, ma non è stata menzionata qui.

Un esempio di come eseguire questa operazione (così come la limitazione di c #) può essere visto in: Uso delle tipiche proprietà get set in C # ... con parametri

Ho estratto il codice da quella risposta:

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

Questo è interessante, ma non sono del tutto sicuro di dove sarebbe utile. myObj.Something ("abc") sembra più come accedere a una funzione che a una proprietà. Non sono sicuro di cosa ti compri.
mattmc3

Odio l'ambiguità. Cosa dovrebbe essere. Un metodo o una proprietà. Alcuni strumenti di refactoring suggeriscono di creare entrambi anche in determinate situazioni, sembra che non sappiano nemmeno ...
brumScouse
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.