Versteckte Funktionen von VB.NET?


121

Ich habe einiges über das Durchsuchen der versteckten Funktionen von C # gelernt und war überrascht, als ich für VB.NET nichts Ähnliches finden konnte.

Also, was sind einige seiner versteckten oder weniger bekannten Merkmale?

Antworten:


128

Die Exception WhenKlausel ist weitgehend unbekannt.

Bedenken Sie:

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
nützlich, wenn Sie eine bestimmte SQLException abfangen möchten, sagen Sie -2, was, wenn ich mich richtig erinnere, ein Netzwerk-Timeout ist: Catch ex als sqlException, wobei ex.code = -2
Pondidum

Beeindruckend! Ich habe das gerade gelesen und es sofort verwendet, um einen Try / Catch-Block zu vereinfachen, den ich letzte Woche geschrieben habe. Ich habe nie neu existiert.
John M Gant

1
+1 Und hier erklärt der NET CLR- Teamblog
MarkJ

5
Dies ist nicht nur versteckt, sondern auch in C # nicht verfügbar.
Cheeso

82

Benutzerdefinierte Enums

Eine der wirklich verborgenen Funktionen von VB ist das completionlistXML-Dokumentations-Tag, mit dem eigene EnumTypen mit erweiterten Funktionen erstellt werden können. Diese Funktion funktioniert jedoch nicht in C #.

Ein Beispiel aus einem meiner jüngsten Codes:

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

Wenn Sie einer als deklarierten Variablen einen Wert zuweisen Rule, bietet die IDE eine IntelliSense-Liste möglicher Werte aus RuleTemplates.

/BEARBEITEN:

Da dies eine Funktion ist, die auf der IDE basiert, ist es schwierig zu zeigen, wie dies aussieht, wenn Sie es verwenden, aber ich verwende nur einen Screenshot:

Abschlussliste in Aktion http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png

Tatsächlich ist IntelliSense zu 100% identisch mit dem, was Sie bei der Verwendung von erhalten Enum.


Interessant - können Sie ein Beispiel dafür zeigen, wie dies aussieht, wenn Sie es konsumieren?
Brian MacKay

Es sieht so aus, als könnte jemand noch seine eigene Regel erstellen, indem er den Regelkonstruktor direkt aufruft. Wenn ja, und wenn Sie dies beenden möchten, können Sie den Konstruktor in Ihrer Bibliothek als "Freund" deklarieren?
Joel Coehoorn

Joel, in meinem Beispielcode habe ich das absichtlich nicht verboten. Vielmehr biete ich dem Benutzer einige gemeinsame Regeln an und erlaube die Erstellung eigener, spezialisierter Regeln. Sie können dies natürlich verhindern, indem Sie den Konstruktor als markieren friendoder dieselbe Klasse wie die Aufzählung verwenden: Ruleanstelle von RuleTemplate.
Konrad Rudolph

Gibt es irgendwo eine Liste mit versteckten nützlichen Attributverwendungen? Dieses auf den ersten Blick scheint unglaublich, aber ich bin mir noch nicht sicher, wo ich es verwenden würde oder ob es in einigen Fällen einen primären Kritikpunkt lösen könnte, wenn es nicht möglich ist, ein Generikum auf Aufzählungen zu beschränken.
Maslow

@ Maslow: Hier ist kein Attribut beteiligt. Das ist ein XML-Kommentar.
Joel Coehoorn

49

Haben Sie den Vergleichsoperator "Gefällt mir" bemerkt?

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

Mehr von 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
warte was? Das ist neu für mich! Hmm, das ist viel besser als die Alternative mit VB.NET-String-Manipulation: D
STW

.. !! Das wusste ich nicht, obwohl ich an mehreren vb.net-Projekten gearbeitet habe! Interessantes Feature ...
Meta-Knight

woooooooooooooooooooooooow! Vielen Dank! Das ist großartig! funktioniert es auch in ELinq, DLinq? Was ist mit XLinq?
Shimmy Weitzhandler

@dotjoe Hmm? An diesen Klumpen ist nichts 'faul'.
Josh Lee

Wie funktioniert das, was passiert unter der Haube? Ist es ein Synonym für reg ex Bibliotheken?
brumScouse

48

Typedefs

VB kennt eine primitive Art von typedefVia- ImportAliasen:

Imports S = System.String

Dim x As S = "Hello"

Dies ist nützlicher, wenn es in Verbindung mit generischen Typen verwendet wird:

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

2
Bitte zeigen Sie ein Beispiel, in dem das Wort Import in meiner IDE nicht erkannt wird.
Shimmy Weitzhandler

5
Importses sollte sein. ;-) Irgendwie ist dieser Fehler seit fast einem Jahr unentdeckt geblieben (und hat 28 positive Stimmen erhalten).
Konrad Rudolph

Ich habe mich immer gefragt, wie ich einen neuen "Typ" mit Standardeinstellungen für ein Generikum erstellen kann! Cool!
Eidylon

3
Import, Import, Importz, was auch immer! Meine Güte, Sie denken, wir haben diese Beiträge gelesen , bevor wir sie positiv bewerten!
MarkJ

Hervorragend für die Verwendung von xunit in visuellen Studiotests, dhImports Assert = xUnit.Assert
Wheelibin

45

Oh! und vergessen Sie nicht XML-Literale .

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

Das wollte ich sagen. Tatsächlich habe ich XML-Literale für einen Zweck verwendet, für den es nicht vorgesehen war. Ich habe es verwendet, um Javascript zu produzieren ... swortham.blogspot.com/2009/03/vb-2008.html
Steve Wortham

9
Unter anderem können Sie XML-Literale verwenden, um das Entkommen hässlicher Zeichenfolgen zu umgehen, z. B. wenn Sie Zeichenfolgen verwenden, die selbst doppelte Anführungszeichen enthalten. Fügen Sie die Zeichenfolge einfach in ein XML-Literal ein und rufen Sie Value wie folgt auf: <string>This string contains "quotes" and it's OK.</string>.Value (Ich fand dies besonders praktisch, wenn ich Tests zum Parsen von CSV-Dateien schrieb, bei denen jedes Feld in Anführungszeichen stand. Es hätte keinen Spaß gemacht, all diese Anführungszeichen von Hand in meinem zu entkommen Testlinien.)
Ryan Lundy

2
@ Kyralessa: +1, toller Kommentar. Tatsächlich ist es auch eine großartige Möglichkeit, mehrzeilige Zeichenfolgen anzugeben (umarmt SQL-Anweisungen usw.).
Heinzi

Inline-XML ist eine der schlechtesten VB.NET-Funktionen, die jemals entwickelt wurden. Unbegründete Tatsache.
Grant Thomas

39

Die Objektinitialisierung ist auch da!

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

1
Ich kann nicht glauben, dass sie mit geschweiften Klammern gingen. Wir haben bereits eine With-Anweisung. Sie hätten diese Syntax einfach wiederverwenden können.
Sam Axe

2
Ich weiß, es ist nur gemacht, um Ihnen zu zeigen, dass es keinen Polizisten auf der Straße gibt ... lol JK
Shimmy Weitzhandler

4
Dies ist der Fall, wenn alle Compiler-Autoren selbst C / C ++ - Programmierer sind. Sie verschieben die C-Syntax immer wieder in andere Sprachen, weil sie sich nichts Besseres vorstellen können.
RBarryYoung

38

DirectCast

DirectCastist ein Wunder. An der Oberfläche funktioniert es ähnlich wie der CTypeOperator, indem es ein Objekt von einem Typ in einen anderen konvertiert. Es funktioniert jedoch nach einem viel strengeren Regelwerk. CTypeDas tatsächliche Verhalten ist daher oft undurchsichtig und es ist überhaupt nicht ersichtlich, welche Art von Konvertierung ausgeführt wird.

DirectCast unterstützt nur zwei verschiedene Operationen:

  • Unboxing eines Werttyps und
  • Upcasting in der Klassenhierarchie.

Jede andere Umwandlung funktioniert nicht (z. B. der Versuch, ein Integerbis a zu entpacken Double) und führt zu einem Kompilierungs- / Laufzeitfehler (abhängig von der Situation und dem, was durch statische Typprüfung erkannt werden kann). Ich verwende daher DirectCastnach Möglichkeit, da dies meine Absicht am besten erfasst: Je nach Situation möchte ich entweder einen Wert bekannten Typs entpacken oder einen Upcast durchführen. Ende der Geschichte.

Unter Verwendung CType, auf der anderen Seite, läßt den Leser des Codes fragen , was wirklich der Programmierer gedacht , weil es für alle Arten von verschiedenen Operationen löst, benutzerdefinierten Code einschließlich Aufruf.

Warum ist das eine versteckte Funktion? Das VB-Team hat eine Richtlinie 1 veröffentlicht , die von der Verwendung DirectCast(obwohl sie tatsächlich schneller ist!) Abrät, um den Code einheitlicher zu gestalten. Ich behaupte, dass dies eine schlechte Richtlinie ist, die umgekehrt werden sollte: Wenn immer möglich, bevorzugen DirectCastSie den allgemeineren CTypeOperator. Es macht den Code viel klarer. CTypesollte dagegen nur aufgerufen werden, wenn dies tatsächlich beabsichtigt ist, dh wenn ein sich verengender CTypeOperator (vgl. Operatorüberladung ) aufgerufen werden soll.


1) Ich kann keinen Link zu der Richtlinie finden, aber ich habe Paul Vicks Einstellung dazu gefunden (Chefentwickler des VB-Teams):

In der realen Welt werden Sie den Unterschied kaum bemerken, daher können Sie sich auch für flexiblere Konvertierungsoperatoren wie CType, CInt usw. entscheiden.


(EDIT von Zack: Erfahren Sie hier mehr: Wie soll ich in VB.NET umwandeln? )


Eigentlich mag ich TryCast () etwas besser. Es wird keine Ausnahme ausgelöst, sondern nur Nothing zurückgegeben, wenn die Besetzung fehlschlägt. Wenn Sie erwarten, dass die Umwandlung häufig fehlschlägt, ist sie schneller als If TypeOf x Is T ... DirectCast (x, T) und sicherlich schneller als das Abfangen der Ausnahme, wenn DirectCast fehlschlägt.
Bob King

6
DirectCast () und TryCast () sind von unschätzbarem Wert, wenn sie korrekt als Paar verwendet werden. DirectCast () sollte verwendet werden, wenn erwartet wird, dass das gegossene Objekt immer der Zieltyp ist (wenn dies nicht der Fall ist, wird ein Fehler angezeigt , eine gute Sache, da es sich um eine unerwartete Situation handelt). TryCast () soll , wenn das Gussobjekt Wesen verwendet werden könnte den Zieltypen oder mehrere Zieltypen. Die ausschließliche Verwendung des einen oder anderen führt entweder zu zusätzlichem Overhead (wenn x der Typ y ist, ist Directcast (x, y) ineffizient) oder zur Vermeidung gültiger Fehler (Verwendung von TryCast () in Fällen, in denen das Objekt immer der Zieltyp sein sollte ).
STW

Yoooder: 100% korrekt. Es ist eine Schande, die ich damals nicht erwähnt habe, TryCastda ich hauptsächlich einen Knochen hatte, den ich mit dem allgegenwärtigen Gebrauch von pflücken konnte CType.
Konrad Rudolph

@ Maslow: Natürlich nicht, da Aufzählungen Werttypen sind und TryCastgemäß der Dokumentation nur für Referenztypen funktionieren.
Konrad Rudolph

+1: Heh. Ich muss zugeben, ich habe das gerade gelesen und dachte: "Oh ja, DirectCast, wie habe ich das vergessen?" Und dann habe ich es in meiner nächsten Codezeile verwendet (da ich CType wirklich nicht mag).
RBarryYoung

37

If Bedingter und Koaleszenzoperator

Ich weiß nicht, wie versteckt Sie es nennen würden, aber die Funktion Iif ([Ausdruck], [Wert, wenn wahr], [Wert, wenn falsch]) als Objekt könnte zählen.

Es ist weniger versteckt als veraltet ! VB 9 hat den IfOperator, der viel besser ist und genau wie der Bedingungs- und Koaleszenzoperator von C # funktioniert (je nachdem, was Sie wollen):

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

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

Bearbeitet, um ein weiteres Beispiel zu zeigen:

Dies funktioniert mit If(), verursacht aber eine Ausnahme mitIIf()

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

Schön, das wusste ich nicht! Ich habe gestern gerade IIF verwendet, also werde ich diesen Codeblock noch einmal besuchen.
Sean Gough

4
Sagen Sie VS 2005 das. Nicht alle von uns arbeiten mit den neuesten und besten.
Sam Erwin

3
@ Slough, Unsinn. Diese Methode ist zu 100% typsicher und gibt ein Objekt des gleichen Typs wie das (zweite und dritte) Argument zurück. Außerdem muss die Konvertierung zwischen den Argumenten erweitert werden, da sonst ein Kompilierungsfehler auftritt, da die Typen nicht übereinstimmen.
Konrad Rudolph

1
Ja, es ist IIf (), das nicht typsicher ist
Pondidum

2
@ Br.Bill Tatsächlich entspricht es vollständig dem :?Operator von C und Perl , es ist nicht nur eine vereinfachte Version.
Konrad Rudolph

32

Das ist schön. Die Select Case-Anweisung in VB.Net ist sehr leistungsfähig.

Klar gibt es den Standard

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

Aber es gibt noch mehr ...

Sie können Bereiche ausführen:

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

Und noch mehr...

Sie können (obwohl dies möglicherweise keine gute Idee ist) mehrere Variablen boolesch prüfen:

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
Tatsächlich haben Sie ein paar verpasst: a) Verwendung von "Select Case True", um mehr als eine Variable zu testen, b) Verwendung von "Case A, B, ..." und sogar c) Anwenden des ":" auf in Zeile die Ausführungsanweisung mit der Bedingungsklausel (obwohl dies vielen nicht gefällt).
RBarryYoung

6
Bitte verwenden Sie nicht Select Case True. Verwenden Sie einfach eine If-Anweisung.
Ryan Lundy

4
Ich finde Select Case True viel einfacher zu lesen als eine riesige ifelse-Aussage.
Dwidel

Das Problem dabei Select Case Trueist, dass es so aussieht, als würde es jede der CaseAnweisungen auswerten und den Code für jede wahr ausführen, was wahr ist. Tatsächlich wertet es sie jedoch einzeln aus und führt nur den Code für den ersten aus , der wahr ist. Die Syntax für Ifist in dieser Hinsicht viel klarer ( If...Else If...Else If...Else).
Ryan Lundy

31

Eine wichtige Zeitersparnis, die ich ständig verwende, ist das Schlüsselwort With :

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

Ich schreibe einfach nicht mehr als ich muss!


Aber es schafft auch einige versteckte Fehler, besonders wenn Sie With in With
Varun Mahajan

2
Ich wusste nicht einmal, dass Sie ein neues Mit in ein bestehendes Mit einfügen können. Das ist nur schlampig!
Bob King

2Bob: Es ist nicht schlampig, würde ich vorschlagen. Es ist nur ein Sprachkonstrukt, das mit Vorsicht verwendet werden muss. Es ist großartig, viele Eigenschaften in aufeinanderfolgenden Zeilen festzulegen, aber es ist keine gute Verwendung der Funktion, ein zufälliges .Foo in einem komplexen Codeteil zu finden und dann die obigen Zeilen der With-Anweisung x zu suchen.
ChrisA

2
Wünschte, C # hat das? Oder habe ich geschlafen und ist das in den C # Hidden-Features bereits Antworten ...? ;-)
PeSHIr

1
@Boo: Du hast Recht, aber es ist immer noch ärgerlich, dass du es nicht zur Beobachtungsliste hinzufügen kannst.
Meta-Knight

31

Der beste und einfachste CSV-Parser:

Microsoft.VisualBasic.FileIO.TextFieldParser

Durch Hinzufügen eines Verweises auf Microsoft.VisualBasic kann dieser in jeder anderen .NET-Sprache verwendet werden, z. B. C #


5
+1 Es ist seltsam, wie die C # -Leute zu FileHelpers laufen, ohne dies jemals zu berücksichtigen. Ich bin sicher, dass FileHelpers ausgezeichnet ist, aber es ist eine externe Abhängigkeit.
MarkJ

@ MarkJ Ich nehme an, es ist wegen Unwissenheit
Nathan Koop

Ich habe verdammt noch mal gegoogelt, um diese Klasse zu finden, und habe es nie getan, danke, dass du sie aufgeschmissen hast!
Pingoo


25

Statische Elemente in Methoden.

Beispielsweise:

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

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

In der obigen Funktion wird der reguläre Musterausdruck immer nur einmal erstellt, unabhängig davon, wie oft die Funktion aufgerufen wird.

Eine andere Verwendung besteht darin, eine Instanz von "zufällig" zu behalten:

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

    Return r.Next()
End Function 

Dies ist auch nicht dasselbe, als es einfach als gemeinsames Mitglied der Klasse zu deklarieren. Artikel, die auf diese Weise deklariert wurden, sind garantiert auch threadsicher. In diesem Szenario spielt es keine Rolle, da sich der Ausdruck niemals ändern wird, aber es gibt andere, bei denen dies der Fall sein könnte.


1
Eine Verwendung davon besteht darin, einen Zähler beizubehalten, der bei jedem Aufruf der Methode erhöht wird. Wenn die Variable als statisch markiert ist, wird sie nicht bei jedem Methodenaufruf neu initialisiert. Es wird erst beim ersten Aufruf initialisiert und behält danach seinen Wert.
Ryan Lundy

Dies ist der Grund, warum statische Klassenmitglieder in VB.NET
Enrico Campidoglio am

Statisch ist in VB.NET noch mehr eine schlechte Form als in klassischem VB. Statische Variablen sollten nach Möglichkeit vermieden werden.
Sam Axe

6
@Boo - das ist ziemlich weitreichend. Was ist Ihre Rechtfertigung? Ich denke, statische Variablen sind nützlich.
MarkJ

4
Statisch, wie in den obigen Beispielen verwendet, ermöglicht eine eindeutige Form der Kapselung: Variablen auf Klassenebene mit Gültigkeitsbereich auf Methodenebene. Ohne sie müssten Sie eine Variable auf Klassenebene erstellen, auf die jedes Klassenmitglied zugreifen kann, selbst wenn Sie sie nur in einer Methode verwenden.
Ryan Lundy

25

In vb gibt es einen Unterschied zwischen diesen Operatoren:

/wird Double
\sich Integerder Rest ignoriert

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
Ich habe das auf die harte Tour gelernt, als ich versucht habe, eine Nadel in einer Million Codezeilen zu finden. reguläre versus ganzzahlige Division. guter Tipp!
Jason Irwin

23

Der in Visual Basic 2005 eingeführte Namespace "My" gefällt mir sehr gut . My ist eine Verknüpfung zu mehreren Gruppen von Informationen und Funktionen. Es bietet schnellen und intuitiven Zugriff auf die folgenden Arten von Informationen:

  • My.Computer : Zugriff auf Informationen zum Computer wie Dateisystem, Netzwerk, Geräte, Systeminformationen usw. Er bietet Zugriff auf eine Reihe sehr wichtiger Ressourcen, darunter My.Computer.Network, My.Computer.FileSystem und My .Computer.Printers.
  • My.Application : Zugriff auf Informationen zur jeweiligen Anwendung wie Name, Version, aktuelles Verzeichnis usw.
  • My.User : Zugriff auf Informationen zum aktuellen authentifizierten Benutzer.
  • My.Resources : Zugriff auf Ressourcen, die von der Anwendung verwendet werden, die sich in stark typisierten Weise in Ressourcendateien befindet.
  • My.Settings : Zugriff auf Konfigurationseinstellungen der Anwendung in stark typisierter Weise.

Das ist einfach großartig und jeder vb.net-Typ da draußen sollte etwas in meinem Namespace wissen, es ist so nützlich.
dr. böse

Meine. * FTW :).
dr. böse

3
Es ist irgendwie nützlich, aber ich hasse den niedergeschlagenen Namen. Erinnert mich an dieses secretgeek.net/refactvb.asp
MarkJ

23

Benutzerdefinierte Ereignisse

Obwohl selten nützlich, kann die Ereignisbehandlung stark angepasst werden:

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

Dies kann dann folgendermaßen getestet werden:

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

scheint cool, aber wenn ich das jemals brauche, denke ich, dass ich etwas falsch gemacht habe ;-). Es scheint nur gegen das KISS-Prinzip.
chrissie1

4
Es ist wirklich sehr nützlich, wenn Sie sicherstellen möchten, dass jede Spüle das Ereignis erhält, auch wenn eine oder mehrere eine Ausnahme auslösen.
Jonathan Allen

Ein weiterer Wert (ich habe ihn gerade auf der MSDN-Site gelesen) ist, dass Ihre Klasse, wenn sie viele Ereignisse auslöst, die Verwendung einer Hash-Tabelle / eines Hash-Wörterbuchs als Container erzwingen kann, anstatt für jedes Ereignis ein Feld zu deklarieren. msdn.microsoft.com/en-us/library/8627sbea(VS.71).aspx
torial

Cool. Ich dachte, dies ist eine der Funktionen, die C # und VB.NET unterscheiden (wie in einer Dose, aber die andere hat keine Syntax dafür). Schön zu wissen, dass ich mich in dieser Hinsicht geirrt habe.
PeSHIr

21

Ich habe gerade einen Artikel über das "!" Operator, auch als "Dictionary Lookup Operator" bekannt. Hier ist ein Auszug aus dem Artikel unter: http://panopticoncentral.net/articles/902.aspx

Der technische Name für die! operator ist der "Dictionary Lookup Operator". Ein Wörterbuch ist ein beliebiger Sammlungstyp, der eher durch einen Schlüssel als durch eine Zahl indiziert wird, genau wie die Einträge in einem englischen Wörterbuch durch das Wort indiziert werden, dessen Definition Sie möchten. Das häufigste Beispiel für einen Wörterbuchtyp ist System.Collections.Hashtable, mit dem Sie der Hashtabelle (Schlüssel-, Wert-) Paare hinzufügen und dann mithilfe der Schlüssel Werte abrufen können. Mit dem folgenden Code werden beispielsweise drei Einträge zu einer Hashtabelle hinzugefügt und einer davon mit dem Schlüssel "Schweinefleisch" nachgeschlagen.

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

Das ! Mit dem Operator können Werte aus jedem Wörterbuchtyp gesucht werden, der seine Werte mithilfe von Zeichenfolgen indiziert. Die Kennung nach dem! wird als Schlüssel für die Suchoperation verwendet. Der obige Code hätte also stattdessen geschrieben werden können:

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

Das zweite Beispiel ist völlig gleichbedeutend mit dem ersten, sieht aber zumindest für meine Augen viel schöner aus. Ich finde, dass es viele Orte gibt, an denen! kann verwendet werden, insbesondere wenn es um XML und das Web geht, wo es nur Tonnen von Sammlungen gibt, die durch Zeichenfolgen indiziert sind. Eine unglückliche Einschränkung ist, dass die Sache nach dem! muss immer noch ein gültiger Bezeichner sein. Wenn die Zeichenfolge, die Sie als Schlüssel verwenden möchten, ein ungültiges Bezeichnerzeichen enthält, können Sie das! Operator. (Sie können beispielsweise nicht "Tabelle! AB $ CD = 5" sagen, da $ in Bezeichnern nicht zulässig ist.) In VB6 und früheren Versionen können Sie Klammern verwenden, um ungültige Bezeichner zu umgehen (z. B. "Tabelle! [AB $") CD] "), aber als wir anfingen, Klammern zu verwenden, um Schlüsselwörter zu umgehen, haben wir die Fähigkeit dazu verloren. In den meisten Fällen,

Um wirklich technisch zu werden, funktioniert x! Y, wenn x eine Standardeigenschaft hat, die einen String oder ein Objekt als Parameter verwendet. In diesem Fall wird x! Y in x.DefaultProperty ("y") geändert. Eine interessante Randnotiz ist, dass es in der lexikalischen Grammatik der Sprache eine spezielle Regel gibt, damit dies alles funktioniert. Das ! Zeichen wird auch als Typzeichen in der Sprache verwendet, und Typzeichen werden vor Operatoren gegessen. Ohne eine spezielle Regel würde x! Y als "x! Y" anstelle von "x! Y" gescannt. Glücklicherweise haben wir, da es in der Sprache keinen Ort gibt, an dem zwei Bezeichner hintereinander gültig sind, die Regel eingeführt, dass, wenn das nächste Zeichen nach dem! ist der Beginn eines Bezeichners, wir betrachten das! ein Operator und kein Typzeichen sein.


11
Das ist eine dieser Funktionen, die ich damals absichtlich vergessen habe. Es spart ein paar Tastenanschläge, beeinträchtigt aber die Hervorhebung und Lesbarkeit meines Codes. wieder richtig vergessen .... JETZT
STW

3
Interessant, aber nicht wirklich nützlich. Ist dies die Art von Dingen, an denen das VB-Team arbeitet, anstatt fehlende Funktionen wie das Yield-Keyword hinzuzufügen? : P
Meta-Knight

5
Diese Funktion wird aus Gründen der Abwärtskompatibilität von VB3 (AFAIK)
Eduardo Molteni

1
Haben die Klassen, die einen Schlüsselindex implementieren, eine gemeinsame Schnittstelle, von der sie erben? wie IKeyed auf die gleiche Weise, wie integer indizierte Container IENumberable implementieren?
Maslow

2
Diese Funktion funktioniert auch mit DataRows (dh dr! ID), was in LINQ to DataSets SEHR praktisch ist.
Paul

19

Dies ist eingebaut und ein klarer Vorteil gegenüber C #. Die Möglichkeit, eine Schnittstellenmethode zu implementieren, ohne denselben Namen verwenden zu müssen.

Sowie:

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

End Sub

Ich bin mir ziemlich sicher, dass Sie so etwas in C # machen können. In VB.NET ist es nur erzwungen und in C # optional?
Jesper Blad Jensen

5
Sie können das Sub auch privat machen. Dies ist eine großartige Möglichkeit, um Dinge wie die Aufrufe von nicht generischen veralteten Versionen von Schnittstellen zu verbergen.
Craig Gidney

3
Es kann eine gute Idee sein. Das klassische Beispiel wäre, wenn Sie eine Public Close-Methode wünschen, die auch als Dispose-Implementierung für IDisposable fungiert.
MarkJ

1
Dies ist auch sehr nützlich, wenn Sie zwei Schnittstellen implementieren, die einen Methodennamen gemeinsam haben.
Eric Nicholson

Ich habe das gesehen und wünschte immer, ich hätte es nicht getan. Sollte nicht erlaubt sein.
FastAl

17

ByVal erzwingen

Wenn Sie in VB Ihre Argumente in zusätzliche Klammern setzen, können Sie die ByRef-Deklaration der Methode überschreiben und in ein ByVal umwandeln. Der folgende Code erzeugt beispielsweise 4, 5, 5 anstelle von 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

Siehe Argument, das nicht durch Prozeduraufruf - zugrunde liegende Variable geändert wird


6
Oh mein Gott ... das ist eine bemerkenswerte Funktion, obwohl ich nicht glaube, dass ich wissen würde, was es tat, wenn ich es im Code eines anderen lese. Wenn Sie es kommentieren müssen, um zu wissen, was es tut, können Sie auch die Wegwerfvariable so einstellen, dass sie stattdessen übergeben wird.
Mattmc3

7
Dies ist eigentlich ein Nebeneffekt der Verwendung von Klammern - Klammern erzeugen einen temporären Wert dessen, was sich darin befindet, selbst wenn nur ein Element vorhanden ist. Dieser Effekt hat mich in vb6 getötet - Unteraufrufe haben keine Parens genommen, aber ich, der ich von C komme, habe die Parens instinktiv eingefügt. 6.0 hat mehrere Parameter in die Luft gesprengt, aber für einen Parameter hat er glücklich einen temporären Wert überschritten und VERWEIGERT, um meine zu ehren 'byref'. Passiert ungefähr alle 3 Jahre, ungefähr zu der Zeit, die ich brauchte, um den letzten Vorfall zu vergessen.
FastAl

16

Übergeben von Parametern nach Namen und, um sie neu zu ordnen

Sub MyFunc(Optional msg as String= "", Optional displayOrder As integer = 0)

    'Do stuff

End function

Verwendung:

Module Module1

    Sub Main()

        MyFunc() 'No params specified

    End Sub

End Module

Kann auch mit der Parameterspezifikation ": =" in beliebiger Reihenfolge aufgerufen werden:

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

Wow, das ist super cool! Ich habe dies bei der Verwendung von Webdiensten usw. gesehen, aber ich wusste nicht, dass Sie dies mit jeder anderen normalen Methode tun können.
RichC

2
Auf jeden Fall ein sehr praktisches Werkzeug, wenn Sie auf eine Methode stoßen, die zu viele Argumente akzeptiert . Ich versuche, jeden Parameter zu benennen und den Namen: = Wert in eine eigene Zeile zu setzen. Es ist viel intuitiver und sauberer für Methoden, die> 5 (meine Faustregel) Parameter verwenden.
STW

Besonders nützlich für die Office-Automatisierung, bei der Sie mit Methoden mit Dutzenden optionaler Argumente umgehen müssen.
MarkJ

1
Was auch cool ist, ist, dass Sie beide mischen können : Geben Sie zunächst die erforderlichen Parameter in der angegebenen Reihenfolge an und wechseln Sie dann zu benannten Parametern für die optionalen Argumente!
RBarryYoung

15

Die Using-Anweisung ist ab VB 8 neu, C # hatte sie von Anfang an. Es ruft die automatische Entsorgung für Sie auf.

Z.B

Using lockThis as New MyLocker(objToLock)

End Using

23
Es ist erwähnenswert (nur weil ich mindestens zweimal vergessen habe), dass Sie mit einer Using-Anweisung mehrere Einwegobjekte umschließen können. Die Syntax lautet "Verwenden von objA als neues Objekt, objB als neues Objekt ...". Es ist viel sauberer als das Verschachteln mehrerer Using-Anweisungen.
STW

Auf jeden Fall auch einer meiner Favoriten.
Sam Axe

14

Import-Aliase sind ebenfalls weitgehend unbekannt:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form

1
Ich denke, wir hatten die gleiche Idee.
chrissie1

3
@Boo - hier ist ein einfaches Beispiel, in dem Import-Aliase nicht böse sind. stackoverflow.com/questions/92869/…
torial

Okay - es gibt einen offensichtlichen Weg für Missbrauch, aber unabhängig von @ torial's Rant ist dies eine großartige Funktion. Jedes Mal, wenn ich System.Text.RegularExpressions einbinde, besteht die Gefahr, dass Namenskollisionen mit der Klasse "Group" auftreten, da dies ein allgemeiner Klassenname ist. Mit dem Alias ​​können Sie vermeiden, dass mehrdeutige Klassen vollständig qualifiziert werden müssen. Dies spart viel Zeit und verbessert die Lesbarkeit bei ordnungsgemäßer Verwendung. Die Funktion ist großartig, aber Ihr spezielles Beispiel lädt zu Spott ein - tut mir leid.
Mattmc3

14

Beachten Sie die folgende Ereignisdeklaration

Public Event SomethingHappened As EventHandler

In C # können Sie mithilfe der folgenden Syntax nach Ereignisabonnenten suchen:

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

Der VB.NET-Compiler unterstützt dies jedoch nicht. Es wird tatsächlich ein verstecktes privates Mitgliedsfeld erstellt, das in IntelliSense nicht sichtbar ist:

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

Mehr Informationen:

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


Warum sollten Sie das jemals tun wollen? Ich kann mir keinen Anwendungsfall vorstellen, bei dem Sie die Anzahl der Abonnenten einer Veranstaltung in VB kennen müssen.
Konrad Rudolph

Unter bestimmten Umständen löst C # eine Ausnahme aus, wenn Sie das Ereignis auslösen und keine Handler vorhanden sind. VB.Net wird nicht. Daher die Notwendigkeit zu überprüfen.
Joel Coehoorn

2
Ich habe dies für ein Geschäftsobjektereignis verwendet, bei dem Validierungsfehlermeldungen an die Abonnenten ausgegeben wurden. Ich wollte überprüfen, ob das Ereignis behandelt wurde, damit ich wusste, dass die Validierungsfehler empfangen wurden. Ansonsten ließ ich das Geschäftsobjekt eine Ausnahme auslösen.
Technobabble

2
Eine weitere praktische Verwendung für dieses private Mitglied besteht darin, die Aufrufliste des Ereignisses abzurufen. Ich habe es in mehreren Fällen verwendet, um das Ereignis für alle Anrufer asynchron auszulösen (verhindert, dass Listener A das Ereignis ändert, bevor Listener B es empfängt; außerdem verhindert es, dass Listener A die Zustellung an Listener B verzögert). Ich habe dies häufig in benutzerdefinierten Datensynchronisierungsszenarien und auch in APIs verwendet.
STW

14

Wenn Sie einen Variablennamen benötigen, der mit dem eines Schlüsselworts übereinstimmt, schließen Sie ihn in Klammern ein. Nicht notwendig. Die beste Vorgehensweise - aber sie kann mit Bedacht eingesetzt werden.

z.B

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

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

zB Beispiel aus Kommentaren (@Pondidum):

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

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

Ich denke, dieses Beispiel wäre besser, wenn Sie nicht "If" als Beispielschlüsselwort verwenden würden.
Sean Gough

4
timer.Start und timer.Stop fallen mir als Beispiele für eine gute Verwendung ein
Pondidum

5
+1 für den Hinweis mit einem Haftungsausschluss. Es gibt mehrere Framework-Klassen, für deren korrekte Auflösung dies erforderlich ist, z. B. [Assembly]
STW,

5
[Enum] ist ein weiteres gutes Beispiel für einen Fall, in dem Sie die Klammern benötigen, um die Klasse anstelle des Schlüsselworts zu verwenden.
Ryan Lundy

13

Es gibt einige Antworten zu XML-Literalen, jedoch nicht zu diesem speziellen Fall:

Sie können XML-Literale verwenden, um Zeichenfolgenliterale einzuschließen, die sonst maskiert werden müssten. String-Literale, die beispielsweise doppelte Anführungszeichen enthalten.

An Stelle von:

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

Du kannst das:

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

Dies ist besonders nützlich, wenn Sie ein Literal für die CSV-Analyse testen:

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

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

(Sie müssen das <string>Tag natürlich nicht verwenden; Sie können jedes beliebige Tag verwenden.)


3
<q>wäre ein gutes Tag, ähnlich der Verwendung in Perl / Ruby. Wie auch immer, das ist eine nette Redewendung. MÖGEN!
Konrad Rudolph

Was für eine geniale Idee. Vielen Dank
Jeremy

12

DateTime kann initialisiert werden, indem Sie Ihr Datum mit # umgeben

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

Sie können zusammen mit dieser Syntax auch die Typinferenz verwenden

Dim independanceDay = #7/4/1776#

Das ist viel schöner als die Verwendung des Konstruktors

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

6
Nicht, wenn Sie Option Strict On haben
danlash

12

Sie können 2 Codezeilen in nur einer Zeile haben. daher:

Dim x As New Something : x.CallAMethod

whoa ... ich dachte, das wäre nur mit Klasse und Vererbung möglich
Jason

Vergessen Sie nichtCall (New Something).CallAMethod()
Jonathan Allen

Dies ist ein Holdever von MS-Basic auf dem Apple] [! In meinem Shop würde ich mich genauso über die Verwendung von Gotos lustig machen: - /
FastAl

Meistens ist dies zu vermeiden, aber wo ich es gerne benutze, sind
Fallanweisungen,

11

Optionale Parameter

Optionale Optionen sind so viel einfacher als das Erstellen neuer Überladungen, wie z.

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

1
Ich wusste nicht, dass C # sie bekommen würde. Sie sind nett, aber Sie müssen darauf achten, sie nur dort zu verwenden, wo Sie sicher sind, dass der Code nicht von C # verwendet wird, da er sie nicht unterstützt. FxCop / Code Analysis weist Sie stattdessen an, die Methode zu überladen.
STW

... Ich habe gerade eine großartige Verwendung für optionale Parameter gefunden, ohne sie jedoch aus dem Produktionscode herauszuhalten. Ich habe einen kurzen Beitrag darüber auf meiner Website geschrieben: yoooder.com/wordpress/?p=62
STW

2
Ah, ich verachte das so sehr ... Aber nützlich für die Office-Automatisierung
dance2die

9

Title Case in VB.Net kann mit einem alten VB6 fxn erreicht werden:

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

1
Es ist auch in der Textinfo-Klasse. Ich bin mir nicht sicher, in welchem ​​Namespace sich das befindet. Wahrscheinlich system.text
Shawn

Sie sollten besser .net-sprachneutral sein und die Globalization TextInfo-Klasse verwenden, um ToTitleCase zu konvertieren. Wenn Ihr Code jemals in C # konvertiert werden muss, haben Sie viele kleine Probleme, die Microsoft erfordern. VisualBasic
Jeremy

9

Eigenschaften mit Parametern

Ich habe einige C # -Programmierungen durchgeführt und eine Funktion entdeckt, die VB.Net fehlte, aber hier nicht erwähnt wurde.

Ein Beispiel dafür (sowie die c # -Einschränkung) finden Sie unter: Verwenden der typischen get set-Eigenschaften in C # ... mit Parametern

Ich habe den Code aus dieser Antwort extrahiert:

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

Das ist interessant, aber ich bin mir nicht ganz sicher, wo dies nützlich wäre. myObj.Something ("abc") sieht eher so aus, als würden Sie auf eine Funktion zugreifen als auf eine Eigenschaft. Ich bin mir nicht sicher, was dir das bringt.
Mattmc3

Ich hasse Mehrdeutigkeiten. Was soll es sein? Eine Methode oder eine Eigenschaft. Einige Refactoring-Tools schlagen vor, beides auch in bestimmten Situationen zu erstellen. Sieht so aus, als ob sie es nicht einmal wissen ...
brumScouse
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.