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?
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
Enum
sEine 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
.
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.
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*"
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)
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>
Objektinitialisierung ist auch dabei!
Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
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:
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? )
If
Bedingter Operator und VereinigungsoperatorIch 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)
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
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 #
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!
(BEARBEITEN: Erfahren Sie hier mehr: Soll ich immer die Operatoren AndAlso und OrElse verwenden? )
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
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.
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:
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
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.
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
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
Ü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")
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
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
Import-Aliase sind ebenfalls weitgehend unbekannt:
Import winf = System.Windows.Forms
''Later
Dim x as winf.Form
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
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.)
Sie können 2 Codezeilen in nur einer Zeile haben. daher:
Dim x As New Something : x.CallAMethod
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)
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
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.
Title Case in VB.Net kann mit einem alten VB6 fxn erreicht werden:
StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
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
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)
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
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.
Sie können ein Wenn in einer Zeile haben.
If True Then DoSomething()
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.)
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
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.
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
Ä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 :-)
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).
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
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.
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
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.
Mit dem Schlüsselwort MyClass können Sie auf die ursprünglich implementierten Klasseninstanzmember verweisen und abgeleitete Klassenüberschreibungen ignorieren.
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
Aliasing von Namespaces
Imports Lan = Langauge
Obwohl dies nicht nur für VB.Net gilt, wird es häufig vergessen, wenn Namespace-Konflikte auftreten.
VB bietet auch die OnError-Anweisung an. Aber heutzutage nützt es nicht viel.
On Error Resume Next
' Or'
On Error GoTo someline
</ code>
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.
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
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:
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
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 .
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)
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)!
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
Dokumentation des Codes
''' <summary>
'''
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub
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.
Wieder optionale Argumente!
Function DoSmtg(Optional a As string, b As Integer, c As String)
'DoSmtg
End
' Call
DoSmtg(,,"c argument")
DoSmtg(,"b argument")
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.
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