webentwicklung-frage-antwort-db.com.de

Versteckte Funktionen von VB.NET?

Ich habe einiges über das Durchsuchen von Hidden Features of C # gelernt und war überrascht, als ich für VB.NET etwas Ähnliches nicht finden konnte.

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

121
Sean Gough

Das Exception When Klausel 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
128
torial

Benutzerdefinierte Enums

Eine der echten versteckten Funktionen von VB ist das XML-Dokumentations-Tag completionlist, das verwendet werden kann Erstellen eigener Enum-ähnlicher Typen mit erweiterter Funktionalität. Diese Funktion funktioniert in C # jedoch nicht.

Ein Beispiel aus einem aktuellen Code von mir:

'
''' <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 nun einer als Rule deklarierten Variablen einen Wert zuweisen, bietet 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 werde nur einen Screenshot verwenden:

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

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

82
Konrad Rudolph

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*"
49
Parsa

Typedefs

VB kennt eine primitive Art von typedef über Import Aliase:

Imports S = System.String

Dim x As S = "Hello"

Dies ist nützlicher in Verbindung mit generischen Typen:

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

Oh! und vergiss nicht XML Literals .

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

Objektinitialisierung ist auch dabei!

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

DirectCast

DirectCast ist ein Wunder. Auf der Oberfläche funktioniert es ähnlich wie der Operator CType, indem es ein Objekt von einem Typ in einen anderen konvertiert. Es funktioniert jedoch nach viel strengeren Regeln. Das tatsächliche Verhalten von CType 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 Wertetyps und
  • upcasting in der Klassenhierarchie.

Jede andere Umwandlung funktioniert nicht (z. B. der Versuch, ein Integer in ein Double zu entpacken) und führt zu einem Kompilierungs-/Laufzeitfehler (abhängig von der Situation und dem, was vom statischen Typ erkannt werden kann) Überprüfung). Ich verwende daher wenn immer möglich DirectCast, da dies meine Absicht am besten erfasst: Abhängig von der Situation möchte ich entweder einen Wert bekannter Art entpacken oder einen Upcast durchführen. Ende der Geschichte.

Wenn Sie dagegen CType verwenden, wundert sich der Leser des Codes, was der Programmierer wirklich beabsichtigt hat, da er alle möglichen Operationen ausführt, einschließlich des Aufrufs von benutzerdefiniertem Code.

Warum ist das eine versteckte Funktion? Das VB Team hat einen Leitfaden veröffentlicht1 Das rät von der Verwendung von DirectCast ab (obwohl es tatsächlich schneller ist!), um den Code einheitlicher zu machen. Ich behaupte, dass dies eine schlechte Richtlinie ist, die umgekehrt werden sollte: Bevorzugen Sie nach Möglichkeit DirectCast gegenüber dem allgemeineren CType -Operator. Es macht den Code viel klarer. CType sollte dagegen nur aufgerufen werden, wenn dies tatsächlich beabsichtigt ist, dh wenn ein sich verengender CType -Operator (vgl. -Operator überlädt ) sollte aufgerufen werden.


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

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.


(BEARBEITEN von Zack: Erfahren Sie hier mehr: Wie soll ich in VB.NET gecastet werden? )

38
Konrad Rudolph

If Bedingter Operator und Vereinigungsoperator

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 nicht so sehr versteckt wie veraltet! VB 9 hat den Operator If, der viel besser ist und genau wie der bedingte Operator und der 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 anderes Beispiel zu zeigen:

Dies funktioniert mit If(), verursacht jedoch eine Ausnahme mit IIf()

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

Dies ist eine schöne. Die Select Case-Anweisung in VB.Net ist sehr mächtig.

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 tun:

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 sogar mehr...

Sie können (auch wenn dies keine gute Idee ist) boolesche Prüfungen für mehrere Variablen durchführen:

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

Der beste und einfachste CSV-Parser:

Microsoft.VisualBasic.FileIO.TextFieldParser

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

31
cjk

Eine große Zeitersparnis, die ich die ganze Zeit nutze, ist das With Schlüsselwort:

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

Ich mag es einfach nicht mehr zu tippen als ich muss!

31
Jasha87
  • AndAlso/OrElse logische Operatoren

(BEARBEITEN: Erfahren Sie hier mehr: Soll ich immer die Operatoren AndAlso und OrElse verwenden? )

26
Joel Coehoorn

In vb gibt es einen Unterschied zwischen diesen Operatoren:

/ ist Double
\ ist Integer und ignoriert den Rest

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
25
Shimmy

Statische Member 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 "random" in der Nähe von:

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

    Return r.Next()
End Function 

Dies ist auch nicht gleichbedeutend damit, es einfach als Shared-Member 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 nie ändern wird, aber es gibt andere, bei denen dies der Fall sein könnte.

25
Joel Coehoorn

Ich mag das "Mein" Namespace, das in Visual Basic 2005 eingeführt wurde. Mein ist eine Verknüpfung zu mehreren Informationsgruppen und Funktionalität. Es bietet schnellen und intuitiven Zugriff auf die folgenden Arten von Informationen:

  • My.Computer: Zugriff auf Informationen zum Computer, z. B. Dateisystem, Netzwerk, Geräte, Systeminformationen usw. Es bietet Zugriff auf eine Reihe sehr wichtiger Ressourcen, einschließlich My.Computer.Network, My .Computer.FileSystem und My.Computer.Printers.
  • My.Application: Zugriff auf anwendungsspezifische Informationen wie Name, Version, aktuelles Verzeichnis usw.
  • My.User: Zugriff auf Informationen zum aktuell authentifizierten Benutzer.
  • My.Resources: Zugriff auf Ressourcen, die von der Anwendung in Ressourcendateien stark typisiert verwendet werden.
  • My.Settings: Zugriff auf Konfigurationseinstellungen der Anwendung stark typisiert.
23
splattne

Benutzerdefinierte Ereignisse

Die Ereignisbehandlung ist zwar selten sinnvoll, kann jedoch 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
23
Konrad Rudolph

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 Auflistungstyp, der nicht durch eine Zahl, sondern durch einen Schlüssel indiziert wird, genau wie die Einträge in einem englischen Wörterbuch durch das zu definierende Wort indiziert werden. Das häufigste Beispiel für einen Wörterbuchtyp ist System.Collections.Hashtable, mit dem Sie Paare (Schlüssel, Wert) zur Hashtabelle hinzufügen und anschließend mithilfe der Schlüssel Werte abrufen können. Der folgende Code fügt beispielsweise drei Einträge zu einer Hash-Tabelle hinzu und schlägt einen davon mit dem Schlüssel "Pork" nach.

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

Das ! Der Operator kann zum Nachschlagen von Werten aus jedem Wörterbuchtyp verwendet werden, der seine Werte mithilfe von Zeichenfolgen indiziert. Die Kennung nach dem! wird als Schlüssel für die Suchoperation verwendet. So könnte der obige Code stattdessen geschrieben worden sein:

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 viel besser aus, zumindest für meine Augen. Ich finde, dass es viele Orte gibt, an denen! kann verwendet werden, insbesondere in Bezug auf XML und das Web, wo es nur Tonnen von Sammlungen gibt, die durch Zeichenfolgen indiziert werden. 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 den! nicht verwenden. 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 ungültige Bezeichner mit Klammern umgehen (z. B. "Tabelle! [AB $ CD] "), aber als wir anfingen, Klammern zu verwenden, um Schlüsselwörter zu umgehen, haben wir die Fähigkeit verloren, dies zu tun. In den meisten Fällen ist dies jedoch keine allzu große Einschränkung.

Um wirklich technisch zu werden, funktioniert x! Y, wenn x eine Standardeigenschaft hat, die einen String oder ein Objekt als Parameter akzeptiert. 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 also x! Y als "x! Y" anstelle von "x! Y" gescannt. Da es in der Sprache keinen Platz gibt, an dem zwei Bezeichner in einer Reihe gültig sind, haben wir die Regel eingeführt, dass, wenn das nächste Zeichen nach dem! Ist der Beginn einer Kennung, betrachten wir die! ein Operator und kein Typ sein.

21
torial

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

Sowie:

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

End Sub
19
torial

Forcen von ByVal

Wenn Sie in VB Ihre Argumente in zusätzliche Klammern setzen, können Sie die ByRef-Deklaration der Methode überschreiben und in ByVal umwandeln. Beispielsweise erzeugt der folgende Code 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 wird durch Prozeduraufruf nicht geändert - zugrunde liegende Variable

17
Chris Haas

Ü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")
16
Rich

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

Z.B.

Using lockThis as New MyLocker(objToLock)

End Using
15
torial

Wenn Sie einen Variablennamen benötigen, der mit dem eines Schlüsselworts übereinstimmt, schließen Sie ihn in eckige Klammern ein. Nicht ang. die beste Übung, aber es 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"

z.B. Beispiel aus Kommentaren (@Pondidum):

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

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

Import-Aliase sind ebenfalls weitgehend unbekannt:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form
14
torial

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. Tatsächlich wird 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.aspxhttp://blogs.msdn.com/vbteam/archive/2009/09/25/ testing-events-for-nothing-null-doug-rothaus.aspx

14
Technobabble

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

Sie können XML-Literale verwenden, um Zeichenfolgenliterale einzuschließen, die ansonsten maskiert werden müssten. Zum Beispiel String-Literale, die 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 nicht das <string> tag natürlich; Sie können ein beliebiges Tag verwenden.)

13
Ryan Lundy

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

Dim x As New Something : x.CallAMethod
12
Parsa

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

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

Sie können bei dieser Syntax auch die Typinferenz verwenden

Dim independanceDay = #7/4/1776#

Das ist viel schöner als mit dem Konstruktor

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

Optionale Parameter

Optionals sind so viel einfacher als das Erstellen neuer Überladungen, wie zum Beispiel:

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

Mehrere Anweisungen zusammen stapeln/gruppieren:

Dim sql As String = "StoredProcedureName"
Using cn As SqlConnection = getOpenConnection(), _
      cmd As New SqlCommand(sql, cn), _
      rdr As SqlDataReader = cmd.ExecuteReader()

    While rdr.Read()

        ''// Do Something

    End While

End Using

Um fair zu sein, können Sie dies auch in C # tun. Aber viele Leute wissen in beiden Sprachen nichts darüber.

9
Joel Coehoorn

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

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

Eigenschaften mit Parametern

Ich habe einige C # -Programmierungen durchgeführt und eine Funktion entdeckt, die bei VB.Net fehlte, hier jedoch 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
9
torial

Eine der Funktionen, die ich als sehr nützlich empfand und die zur Behebung vieler Fehler beigetragen haben, ist die explizite Übergabe von Argumenten an Funktionen, insbesondere bei Verwendung von optional.

Hier ist ein Beispiel:

Public Function DoSomething(byval x as integer, optional y as boolean=True, optional z as boolean=False)
' ......
End Function

dann kannst du es so nennen:

DoSomething(x:=1, y:=false)
DoSomething(x:=2, z:=true)
or
DoSomething(x:=3,y:=false,z:=true)

Dies ist viel sauberer und fehlerfrei, wenn Sie die Funktion wie folgt aufrufen

DoSomething(1,true)
8
Youssef

Verbesserte Fehlerbehandlung mit When

Beachten Sie die Verwendung von when in der Zeile Catch ex As IO.FileLoadException When attempt < 3

Do
  Dim attempt As Integer
  Try
    ''// something that might cause an error.
  Catch ex As IO.FileLoadException When attempt < 3
    If MsgBox("do again?", MsgBoxStyle.YesNo) = MsgBoxResult.No Then
      Exit Do
    End If
  Catch ex As Exception
    ''// if any other error type occurs or the attempts are too many
    MsgBox(ex.Message)
    Exit Do
  End Try
  ''// increment the attempt counter.
  attempt += 1
Loop

Kürzlich angesehen in VbRad

7
Eduardo Molteni

Wenn Sie noch nie von Folgendem gewusst haben, werden Sie nicht glauben, dass es wahr ist, dann fehlt C # wirklich viel Zeit:

(Es heißt XML-Literale)

Imports <xmlns:xs="System">

Module Module1

  Sub Main()
    Dim xml =
      <root>
        <customer id="345">
          <name>John</name>
          <age>17</age>
        </customer>
        <customer id="365">
          <name>Doe</name>
          <age>99</age>
        </customer>
      </root>

    Dim id = 1
    Dim name = "Beth"
    DoIt(
      <param>
        <customer>
          <id><%= id %></id>
          <name><%= name %></name>
        </customer>
      </param>
    )

    Dim names = xml...<name>
    For Each n In names
      Console.WriteLine(n.Value)
    Next

    For Each customer In xml.<customer>
      Console.WriteLine("{0}: {1}", [email protected], customer.<age>.Value)
    Next

    Console.Read()
  End Sub

  Private Sub CreateClass()
    Dim CustomerSchema =
      XDocument.Load(CurDir() & "\customer.xsd")

    Dim fields =
      From field In CustomerSchema...<xs:element>
      Where [email protected] IsNot Nothing
      Select
        Name = [email protected],
        Type = [email protected]

    Dim customer = 
      <customer> Public Class Customer 
<%= From field In fields Select <f> 
Private m_<%= field.Name %> As <%= GetVBPropType(field.Type) %></f>.Value %>

                     <%= From field In fields Select <p> 
Public Property <%= field.Name %> As <%= GetVBPropType(field.Type) %>
 Get 
Return m_<%= field.Name %> 
End Get
 Set(ByVal value As <%= GetVBPropType(field.Type) %>)
 m_<%= field.Name %> = value 
End Set
 End Property</p>.Value %> 
End Class</customer>

    My.Computer.FileSystem.WriteAllText("Customer.vb",
                                        customer.Value,
                                        False,
                                        System.Text.Encoding.ASCII)

  End Sub

  Private Function GetVBPropType(ByVal xmlType As String) As String
    Select Case xmlType
      Case "xs:string"
        Return "String"
      Case "xs:int"
        Return "Integer"
      Case "xs:decimal"
        Return "Decimal"
      Case "xs:boolean"
        Return "Boolean"
      Case "xs:dateTime", "xs:date"
        Return "Date"
      Case Else
        Return "'TODO: Define Type"
    End Select
  End Function

  Private Sub DoIt(ByVal param As XElement)
    Dim customers =
      From customer In param...<customer>
      Select New Customer With
      {
        .ID = customer.<id>.Value,
        .FirstName = customer.<name>.Value
      }

    For Each c In customers
      Console.WriteLine(c.ToString())
    Next
  End Sub

  Private Class Customer
    Public ID As Integer
    Public FirstName As String
    Public Overrides Function ToString() As String
      Return <string>
ID : <%= Me.ID %>
Name : <%= Me.FirstName %>
             </string>.Value
    End Function

  End Class
End Module
'Results:

ID : 1
Name : Beth
John
Doe
345: 17
365: 99

Schauen Sie sich XML Literals Tips/Tricks von Beth Massi an.

7
Shimmy

Sie können ein Wenn in einer Zeile haben.

If True Then DoSomething()
7
Parsa
  • Untergeordnete Namespaces sind nach dem Importieren der übergeordneten Namespaces im Gültigkeitsbereich. Anstatt beispielsweise System.IO zu importieren oder System.IO.File zu sagen, um die File-Klasse zu verwenden, können Sie IO.File sagen. Das ist ein einfaches Beispiel: Es gibt Stellen, an denen die Funktion wirklich nützlich ist, und C # tut dies nicht.
7
Joel Coehoorn

Hier ist eine lustige, die ich nicht gesehen habe; Ich weiß, dass es in VS 2008 funktioniert, zumindest:

Wenn Sie versehentlich Ihre VB) - Zeile mit einem Semikolon beenden, weil Sie zu viel C # getan haben, das Semikolon wird automatisch entfernt. Es ist tatsächlich unmöglich (zumindest in VS 2008), versehentlich eine VB=) - Zeile mit einem Semikolon zu beenden.

(Es ist nicht perfekt. Wenn Sie das Semikolon in der Mitte Ihres endgültigen Klassennamens eingeben, wird der Klassenname nicht automatisch vervollständigt.)

6
Ryan Lundy

Im Gegensatz zu break in C-Sprachen in VB) können Sie Exit oder Continue den Block, den Sie möchten:

For i As Integer = 0 To 100
    While True
        Exit While
        Select Case i
            Case 1
                Exit Select
            Case 2
                Exit For
            Case 3
                Exit While
            Case Else
                Exit Sub
        End Select
        Continue For
    End While
Next
6
Parsa
IIf(False, MsgBox("msg1"), MsgBox("msg2"))

Was ist das Ergebnis? zwei Meldungsfelder !!!! Dies geschieht, weil die IIf-Funktion beim Erreichen der Funktion beide Parameter auswertet.

VB hat einen neuen If-Operator (genau wie C #?: Operator):

If(False, MsgBox("msg1"), MsgBox("msg2"))

Zeigt nur die zweite msgbox an.

im Allgemeinen würde ich empfehlen, alle IIFs in Ihrem vb-Code zu ersetzen, es sei denn, Sie wollten, dass beide Elemente ausgewertet werden:

Dim value = IIf(somthing, LoadAndGetValue1(), LoadAndGetValue2())

sie können sicher sein, dass beide Werte geladen wurden.

5
Shimmy

Sie können reservierte Schlüsselwörter für Eigenschaften und Variablennamen verwenden, wenn Sie den Namen mit [und] umgeben.

Public Class Item
    Private Value As Integer
    Public Sub New(ByVal value As Integer)
        Me.Value = value
    End Sub

    Public ReadOnly Property [String]() As String
        Get
            Return Value
        End Get
    End Property

    Public ReadOnly Property [Integer]() As Integer
        Get
            Return Value
        End Get
    End Property

    Public ReadOnly Property [Boolean]() As Boolean
        Get
            Return Value
        End Get
    End Property
End Class

'Real examples:
Public Class PropertyException : Inherits Exception
    Public Sub New(ByVal [property] As String)
        Me.Property = [property]
    End Sub

    Private m_Property As String
    Public Property [Property]() As String
        Get
            Return m_Property
        End Get
        Set(ByVal value As String)
            m_Property = value
        End Set
    End Property
End Class

Public Enum LoginLevel
    [Public] = 0
    Account = 1
    Admin = 2
    [Default] = Account
End Enum
5
Shimmy

Ähnlich wie Parsa's answer hat like operator viele Dinge, mit denen es über und hinweg übereinstimmen kann über einfachen Wildcards. Ich bin fast von meinem Stuhl gefallen, als ich das MSDN-Dokument darauf gelesen habe :-)

5
Dan F

Wenn Sie in VB8 und früheren Versionen keinen Typ für die von Ihnen eingeführte Variable angegeben haben, wurde der Objekttyp automatisch erkannt. In VB9 (2008) verhält sich das Dim wie das var - Schlüsselwort von C #, wenn die Option Infer auf On gesetzt ist (dies ist standardmäßig der Fall).

5
Parsa

Wählen Sie Groß-/Kleinschreibung anstelle mehrerer If/ElseIf/Else-Anweisungen aus.

Nehmen Sie in diesem Beispiel einfache Geometrieobjekte an:

Function GetToString(obj as SimpleGeomertyClass) as String
  Select Case True
    Case TypeOf obj is PointClass
      Return String.Format("Point: Position = {0}", _
                            DirectCast(obj,Point).ToString)
    Case TypeOf obj is LineClass
      Dim Line = DirectCast(obj,LineClass)
      Return String.Format("Line: StartPosition = {0}, EndPosition = {1}", _
                            Line.StartPoint.ToString,Line.EndPoint.ToString)
    Case TypeOf obj is CircleClass
      Dim Line = DirectCast(obj,CircleClass)
      Return String.Format("Circle: CenterPosition = {0}, Radius = {1}", _
                            Circle.CenterPoint.ToString,Circle.Radius)
    Case Else
      Return String.Format("Unhandled Type {0}",TypeName(obj))
  End Select
End Function
5
Clif

Verwenden Sie beim Deklarieren eines Arrays in vb.net immer die Syntax "0 bis xx".

Dim b(0 to 9) as byte 'Declares an array of 10 bytes

Dies macht die Spannweite des Arrays sehr deutlich. Vergleichen Sie es mit dem Äquivalent

Dim b(9) as byte 'Declares another array of 10 bytes

Auch wenn Sie wissen, dass das zweite Beispiel aus 10 Elementen besteht, fühlt es sich einfach nicht offensichtlich an. Und ich kann mich nicht erinnern, wie oft ich Code von einem Programmierer gesehen habe, der das oben Gesagte wollte, aber stattdessen schrieb

Dim b(10) as byte 'Declares another array of 10 bytes

Das ist natürlich völlig falsch. As b(10) erstellt ein Array von 11 Bytes. Und es kann leicht zu Fehlern führen, da es für jeden richtig aussieht, der nicht weiß, wonach er suchen soll.

Die Syntax "0 bis xx" funktioniert auch mit der folgenden

Dim b As Byte() = New Byte(0 To 9) {} 'Another way to create a 10 byte array
ReDim b(0 to 9) 'Assigns a new 10 byte array to b

Wenn Sie die vollständige Syntax verwenden, zeigen Sie auch jedem, der Ihren Code in Zukunft liest, dass Sie wissen, was Sie getan haben.

5
Marcus Andrén

Anders als in C # können Sie sich in VB auf die Standardwerte für nicht nullfähige Elemente verlassen:

Sub Main()
    'Auto assigned to def value'
    Dim i As Integer '0'
    Dim dt As DateTime '#12:00:00 AM#'
    Dim a As Date '#12:00:00 AM#'
    Dim b As Boolean 'False'

    Dim s = i.ToString 'valid
End Sub

In C # ist dies ein Compilerfehler:

int x;
var y = x.ToString(); //Use of unassigned value
4
Shimmy

Beachten Sie auch, dass VB.NET-Projekte standardmäßig über einen Stammnamespace verfügen, der Teil der Projekteigenschaften ist. Standardmäßig hat dieser Root-Namespace denselben Namen wie das Projekt. Bei Verwendung der Namespace-Blockstruktur werden Namen tatsächlich an diesen Stammnamespace angehängt. Beispiel: Wenn das Projekt MyProject heißt, können wir eine Variable wie folgt deklarieren:

Private obj As MyProject.MyNamespace.MyClass

Verwenden Sie die Menüoption Projekt -> Eigenschaften, um den Stammnamespace zu ändern. Der Root-Namespace kann ebenfalls gelöscht werden, dh alle Namespace-Blöcke werden zur Root-Ebene für den enthaltenen Code.

4
Nescio

Mit dem Schlüsselwort MyClass können Sie auf die ursprünglich implementierten Klasseninstanzmember verweisen und abgeleitete Klassenüberschreibungen ignorieren.

4
Parsa

Das Schlüsselwort Nothing kann je nach Kontext default (T) oder null bedeuten. Sie können dies ausnutzen, um eine sehr interessante Methode zu erstellen:

'''<summary>Returns true for reference types, false for struct types.</summary>'
Public Function IsReferenceType(Of T)() As Boolean
    Return DirectCast(Nothing, T) Is Nothing
End Function
4
Craig Gidney

Aliasing von Namespaces

Imports Lan = Langauge

Obwohl dies nicht nur für VB.Net gilt, wird es häufig vergessen, wenn Namespace-Konflikte auftreten.

3
chrissie1

VB bietet auch die OnError-Anweisung an. Aber heutzutage nützt es nicht viel.

On Error Resume Next
' Or'
On Error GoTo someline
</ code>
3
Parsa

Sie können REM zum Auskommentieren einer Zeile anstelle von '. Nicht besonders nützlich, hilft aber dabei, wichtige Kommentare hervorzuheben, ohne "!!!!!!!" oder was auch immer zu verwenden.

2
Booji Boy

Nullable Dates! Dies ist besonders in Fällen nützlich, in denen Daten in eine Datenbank eingegeben werden oder aus einer Datenbank entnommen werden (in diesem Fall MSSQL Server). Ich habe zwei Verfahren, um mir einen SmallDateTime-Parameter zu geben, der mit einem Wert gefüllt ist. Einer von ihnen nimmt ein einfaches altes Datum und prüft, ob es irgendeinen Wert enthält, wobei er ein Standarddatum zuweist. Die andere Version akzeptiert ein Nullable(Of Date), so dass ich das Datum wertlos lassen kann und akzeptiere, was auch immer die Standardeinstellung von der gespeicherten Prozedur war

<System.Diagnostics.DebuggerStepThrough> _
Protected Function GP(ByVal strName As String, ByVal dtValue As Date) As SqlParameter
    Dim aParm As SqlParameter = New SqlParameter
    Dim unDate As Date
    With aParm
        .ParameterName = strName
        .Direction = ParameterDirection.Input
        .SqlDbType = SqlDbType.SmallDateTime
        If unDate = dtValue Then    'Unassigned variable
            .Value = "1/1/1900 12:00:00 AM" 'give it a default which is accepted by smalldatetime
        Else
            .Value = CDate(dtValue.ToShortDateString)
        End If
    End With
    Return aParm
End Function
<System.Diagnostics.DebuggerStepThrough()> _
Protected Function GP(ByVal strName As String, ByVal dtValue As Nullable(Of Date)) As SqlParameter
    Dim aParm As SqlParameter = New SqlParameter
    Dim unDate As Date
    With aParm
        .ParameterName = strName
        .Direction = ParameterDirection.Input
        .SqlDbType = SqlDbType.SmallDateTime
        If dtValue.HasValue = False Then
            '// it's nullable, so has no value
        ElseIf unDate = dtValue.Value Then    'Unassigned variable
            '// still, it's nullable for a reason, folks!
        Else
            .Value = CDate(dtValue.Value.ToShortDateString)
        End If
    End With
    Return aParm
End Function
2
Private Sub Button1_Click(ByVal sender As Button, ByVal e As System.EventArgs)
        Handles Button1.Click
    sender.Enabled = True
    DisableButton(sender)
End Sub

Private Sub Disable(button As Object)
    button.Enabled = false
End Sub

In diesem Snippet haben Sie zwei (vielleicht noch mehr?) Dinge, die Sie in C # niemals tun könnten:

  1. Handles Button1.Click - Hängt einen Handler extern an das Event an!
  2. Die implizite Angabe von VB ermöglicht es Ihnen, den ersten Parameter des Handlers als den expexted-Typ zu deklarieren. In C # können Sie einen Delegaten nicht an ein anderes Muster adressieren, auch wenn es sich um den erwarteten Typ handelt.

Außerdem können Sie in C # die erwartete Funktionalität für Objekte nicht verwenden. In C # können Sie davon träumen (jetzt haben sie das dynamische Schlüsselwort erstellt, aber es ist weit entfernt von VB). Wenn Sie in C # schreiben (new object (). Enabled), erhalten Sie die Fehlermeldung, dass Typ object keine Methode 'Enabled' hat. Jetzt bin ich nicht derjenige, der Ihnen empfehlen wird, ob dies sicher ist oder nicht. Die Informationen werden OHNE MÄNGELGEWÄHR zur Verfügung gestellt. Machen Sie es auf eigene Faust, fahren Sie trotzdem, manchmal (wie bei der Arbeit mit COM-Objekten) ist dies so eine gute Sache. Ich persönlich schreibe immer (Absender als Button), wenn der erwartete Wert sicher ein Button ist.

Eigentlich übrigens: nimm dieses Beispiel:

Private Sub control_Click(ByVal sender As Control, ByVal e As System.EventArgs)
        Handles TextBox1.Click, CheckBox1.Click, Button1.Click
    sender.Text = "Got it?..."
End Sub
2
Shimmy

Es ist nicht möglich, Schnittstellenmember explizit in VB zu implementieren, aber es ist möglich, sie mit einem anderen Namen zu implementieren.

Interface I1
    Sub Foo()
    Sub TheFoo()
End Interface

Interface I2
    Sub Foo()
    Sub TheFoo()
End Interface

Class C
    Implements I1, I2

    Public Sub IAmFoo1() Implements I1.Foo
        ' Something happens here'
    End Sub

    Public Sub IAmFoo2() Implements I2.Foo
        ' Another thing happens here'
    End Sub

    Public Sub TheF() Implements I1.TheFoo, I2.TheFoo
        ' You shouldn't yell!'
    End Sub
End Class

Bitte stimmen Sie für diese Funktion bei Microsoft Connect ab .

2
Parsa

Ich weiß nicht, wie versteckt Sie es nennen würden, aber der Operator If könnte zählen.

In gewisser Weise ist es dem ?: (ternär) oder der ?? Operator in vielen C-ähnlichen Sprachen. Es ist jedoch wichtig zu beachten, dass alle Parameter ausgewertet werden. Daher ist es wichtig, nichts weiterzugeben, das eine Ausnahme verursachen kann (es sei denn, Sie möchten dies möchten) oder etwas, das unbeabsichtigte Nebenwirkungen verursachen kann.

Verwendung:

Dim result = If(condition, valueWhenTrue, valueWhenFalse)
Dim value = If(obj, valueWhenObjNull)
2
Sam Erwin

Früher mochte ich optionale Funktionsparameter sehr, aber jetzt, wo ich viel zwischen C # und VB) hin und her wechseln muss, verwende ich sie weniger. Wann wird C # sie unterstützen? C++ und sogar C hatte sie (von einer Art)!

1
Joel Coehoorn

Unterschiede zwischen den Schlüsselwörtern ByVal und ByRef:

Module Module1

    Sub Main()
        Dim str1 = "initial"
        Dim str2 = "initial"
        DoByVal(str1)
        DoByRef(str2)

        Console.WriteLine(str1)
        Console.WriteLine(str2)
    End Sub

    Sub DoByVal(ByVal str As String)
        str = "value 1"
    End Sub

    Sub DoByRef(ByRef str As String)
        str = "value 2"
    End Sub
End Module

'Results:
'initial
'value 2
1
Shimmy

Dokumentation des Codes

''' <summary>
''' 
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub
1
PdotWang

Irgendwann haben Basic-Benutzer keine Variablen eingeführt. Sie stellten sie nur vor, indem sie sie benutzten. VBs Option Explicit wurde eingeführt, um sicherzustellen, dass Sie keine Variable versehentlich durch falsches Tippen einführen. Sie können es jederzeit deaktivieren und die Tage erleben, an denen wir mit Basic gearbeitet haben.

1
Parsa

Wieder optionale Argumente!

Function DoSmtg(Optional a As string, b As Integer, c As String)
    'DoSmtg
End 

' Call
DoSmtg(,,"c argument")

DoSmtg(,"b argument")
0
Hedi Guizani

Attribute für Methoden! Beispielsweise kann eine Eigenschaft, die zur Entwurfszeit nicht verfügbar sein sollte, 1) im Eigenschaftenfenster ausgeblendet, 2) nicht serialisiert werden (besonders ärgerlich für Benutzersteuerelemente oder für Steuerelemente, die aus einer Datenbank geladen werden):

<System.ComponentModel.Browsable(False), _
System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden), _
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always), _
System.ComponentModel.Category("Data")> _
Public Property AUX_ID() As String
    <System.Diagnostics.DebuggerStepThrough()> _
     Get
        Return mAUX_ID
    End Get
    <System.Diagnostics.DebuggerStepThrough()> _
     Set(ByVal value As String)
        mAUX_ID = value
    End Set
End Property

Das Einfügen der Funktion DebuggerStepThrough() ist auch sehr hilfreich, wenn Sie eine Menge Debugging ausführen (beachten Sie, dass Sie in der Funktion immer noch einen Haltepunkt setzen können oder was auch immer, aber Sie können ' t Schritt für Schritt durch diese Funktion).

Die Möglichkeit, Objekte in Kategorien einzuteilen (z. B. "Daten"), bedeutet auch, dass die Eigenschaft im Eigenschaften-Tool angezeigt werden soll, wenn Sie möchten -Fenster, diese bestimmte Eigenschaft wird in dieser Kategorie angezeigt.

0
Sub Main()
    Select Case "value to check"
        'Check for multiple items at once:'
        Case "a", "b", "asdf" 
            Console.WriteLine("Nope...")
        Case "value to check"
            Console.WriteLine("Oh yeah! thass what im talkin about!")
        Case Else
            Console.WriteLine("Nah :'(")
    End Select


    Dim jonny = False
    Dim charlie = True
    Dim values = New String() {"asdff", "asdfasdf"}
    Select Case "asdfasdf"
        'You can perform boolean checks that has nothing to do with your var.,
        'not that I would recommend that, but it exists.'
        Case values.Contains("ddddddddddddddddddddddd")
        Case True
        Case "No sense"
        Case Else
    End Select

    Dim x = 56
    Select Case x
        Case Is > 56
        Case Is <= 5
        Case Is <> 45
        Case Else
    End Select

End Sub
0
Shimmy