J'ai beaucoup appris en parcourant Caractéristiques cachées de C # et j'ai été surpris de ne pas trouver quelque chose de similaire pour VB.NET.
Alors, quelles sont certaines de ses fonctionnalités cachées ou moins connues?
Le Exception When
la clause est largement inconnue.
Considère ceci:
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
s personnaliséL'une des fonctionnalités réelles cachées de VB est la balise de documentation XML completionlist
qui peut être utilisée pour créer ses propres types de type Enum
avec des fonctionnalités étendues. Cette fonctionnalité ne fonctionne cependant pas en C #.
Un exemple tiré d'un de mes récents 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
Maintenant, lors de l'attribution d'une valeur à une variable déclarée comme Rule
, le IDE propose une liste IntelliSense des valeurs possibles de RuleTemplates
.
Comme il s'agit d'une fonctionnalité qui repose sur l'IDE, il est difficile de montrer à quoi cela ressemble lorsque vous l'utilisez, mais je vais simplement utiliser une capture d'écran:
Liste d'achèvement en action http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png
En fait, l'IntelliSense est 100% identique à ce que vous obtenez lorsque vous utilisez un Enum
.
Avez-vous remarqué l'opérateur de comparaison Like?
Dim b As Boolean = "file.txt" Like "*.txt"
Plus de 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 connaît un type primitif d'alias typedef
via Import
:
Imports S = System.String
Dim x As S = "Hello"
Ceci est plus utile lorsqu'il est utilisé en conjonction avec des types génériques:
Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)
Oh! et n'oubliez pas Littéraux XML .
Dim contact2 = _
<contact>
<name>Patrick Hines</name>
<%= From p In phoneNumbers2 _
Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
%>
</contact>
L'initialisation des objets est là aussi!
Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
DirectCast
DirectCast
est une merveille. En surface, il fonctionne de manière similaire à l'opérateur CType
en ce qu'il convertit un objet d'un type en un autre. Cependant, cela fonctionne selon un ensemble de règles beaucoup plus strictes. Le comportement réel de CType
est donc souvent opaque et il n'est pas du tout évident quel type de conversion est exécuté.
DirectCast
ne prend en charge que deux opérations distinctes:
Toute autre distribution ne fonctionnera pas (par exemple, essayer de décompresser un Integer
en Double
) et entraînera une erreur de compilation/d'exécution (en fonction de la situation et de ce qui peut être détecté par le type statique) vérification). J'utilise donc DirectCast
chaque fois que cela est possible, car cela reflète au mieux mon intention: selon la situation, je souhaite soit déballer une valeur de type connu, soit effectuer une conversion ascendante. Fin de l'histoire.
L'utilisation de CType
, d'autre part, laisse le lecteur du code se demander ce que le programmeur voulait vraiment car il résout toutes sortes d'opérations différentes, y compris l'appel de code défini par l'utilisateur.
Pourquoi est-ce une fonctionnalité cachée? L'équipe VB a publié une directive1 cela décourage l'utilisation de DirectCast
(même si c'est en fait plus rapide!) afin de rendre le code plus uniforme. Je soutiens qu'il s'agit d'une mauvaise directive qui devrait être inversée: Dans la mesure du possible, privilégiez DirectCast
par rapport à l'opérateur plus général CType
. Cela rend le code beaucoup plus clair. CType
, en revanche, ne doit être appelé que si cela est effectivement prévu, c'est-à-dire lorsqu'un opérateur CType
rétrécissant (cf. surcharge de l'opérateur ) doit être appelé.
1) Je ne suis pas en mesure de trouver un lien vers la ligne directrice, mais j'ai trouvé le point de vue de Paul Vick (développeur en chef de l'équipe VB):
Dans le monde réel, vous ne remarquerez presque jamais la différence, vous pourriez donc aussi bien opter pour les opérateurs de conversion plus flexibles comme CType, CInt, etc.
(EDIT par Zack: En savoir plus ici: Comment dois-je caster en VB.NET? )
If
opérateur conditionnel et coalescentJe ne sais pas à quel point vous pourriez l'appeler, mais la fonction Iif ([expression], [valeur si vraie], [valeur si fausse]) As pourrait compter.
Ce n'est pas tellement caché que obsolète! VB 9 a l'opérateur If
qui est bien meilleur et fonctionne exactement comme l'opérateur conditionnel et de fusion de C # (selon ce que vous voulez):
Dim x = If(a = b, c, d)
Dim hello As String = Nothing
Dim y = If(hello, "World")
Modifié pour montrer un autre exemple:
Cela fonctionnera avec If()
, mais provoquera une exception avec IIf()
Dim x = If(b<>0,a/b,0)
Ceci est une belle. L'instruction Select Case dans VB.Net est très puissante.
Bien sûr, il y a la norme
Select Case Role
Case "Admin"
''//Do X
Case "Tester"
''//Do Y
Case "Developer"
''//Do Z
Case Else
''//Exception case
End Select
Mais il y a plus ...
Vous pouvez faire des gammes:
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
Et encore plus...
Vous pouvez (bien que ce ne soit pas une bonne idée) faire des vérifications booléennes sur plusieurs variables:
Select Case True
Case a = b
''//Do X
Case a = c
''//Do Y
Case b = c
''//Do Z
Case Else
''//Exception case
End Select
Le meilleur et simple analyseur CSV:
Microsoft.VisualBasic.FileIO.TextFieldParser
En ajoutant une référence à Microsoft.VisualBasic, cela peut être utilisé dans n'importe quel autre langage .Net, par exemple C #
Un gain de temps majeur que j'utilise tout le temps est le mot-clé With:
With ReallyLongClassName
.Property1 = Value1
.Property2 = Value2
...
End With
Je n'aime simplement pas taper plus que je ne le dois!
(EDIT: En savoir plus ici: Dois-je toujours utiliser les opérateurs AndAlso et OrElse? )
Dans vb, il existe une différence entre ces opérateurs:
/
est Double
\
est Integer
en ignorant le reste
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
membres statiques dans les méthodes.
Par exemple:
Function CleanString(byval input As String) As String
Static pattern As New RegEx("...")
return pattern.Replace(input, "")
End Function
Dans la fonction ci-dessus, l'expression régulière du motif ne sera créée qu'une seule fois, quel que soit le nombre de fois que la fonction est appelée.
Une autre utilisation consiste à conserver une instance de "random" autour:
Function GetNextRandom() As Integer
Static r As New Random(getSeed())
Return r.Next()
End Function
En outre, ce n'est pas la même chose que de simplement le déclarer en tant que membre partagé de la classe; les éléments déclarés de cette façon sont également garantis pour les threads. Cela n'a pas d'importance dans ce scénario car l'expression ne changera jamais, mais il y en a d'autres où cela pourrait.
J'aime vraiment le "My" Namespace qui a été introduit dans Visual Basic 2005. Mon est un raccourci vers plusieurs groupes d'informations et fonctionnalité. Il offre un accès rapide et intuitif aux types d'informations suivants:
Bien que rarement utile, la gestion des événements peut être fortement personnalisée:
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
Cela peut ensuite être testé de la manière suivante:
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
Je viens de trouver un article parlant du "!" , également appelé "opérateur de recherche de dictionnaire". Voici un extrait de l'article à: http://panopticoncentral.net/articles/902.aspx
Le nom technique du! L'opérateur est "l'opérateur de recherche de dictionnaire". Un dictionnaire est tout type de collection qui est indexé par une clé plutôt que par un nombre, tout comme la façon dont les entrées d'un dictionnaire anglais sont indexées par le mot dont vous voulez la définition. L'exemple le plus courant d'un type de dictionnaire est le System.Collections.Hashtable, qui vous permet d'ajouter des paires (clé, valeur) dans la table de hachage, puis de récupérer des valeurs à l'aide des clés. Par exemple, le code suivant ajoute trois entrées à une table de hachage et recherche l'une d'entre elles à l'aide de la clé "Porc".
Dim Table As Hashtable = New Hashtable
Table("Orange") = "A fruit"
Table("Broccoli") = "A vegetable"
Table("Pork") = "A meat"
Console.WriteLine(Table("Pork"))
Le ! L'opérateur peut être utilisé pour rechercher des valeurs à partir de n'importe quel type de dictionnaire qui indexe ses valeurs à l'aide de chaînes. L'identifiant après le! est utilisé comme clé dans l'opération de recherche. Ainsi, le code ci-dessus aurait pu être écrit à la place:
Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)
Le deuxième exemple est complètement équivalent au premier, mais semble beaucoup plus agréable, du moins à mes yeux. Je trouve qu'il y a beaucoup d'endroits où! peut être utilisé, en particulier en ce qui concerne XML et le Web, où il n'y a que des tonnes de collections indexées par chaîne. Une limitation malheureuse est que la chose qui suit le! doit toujours être un identifiant valide, donc si la chaîne que vous souhaitez utiliser comme clé contient un caractère identifiant non valide, vous ne pouvez pas utiliser le! opérateur. (Vous ne pouvez pas, par exemple, dire "Table! AB $ CD = 5" car $ n'est pas légal dans les identifiants.) Dans VB6 et avant, vous pouvez utiliser des crochets pour échapper aux identifiants invalides (ie "Table! [AB $ CD] "), mais lorsque nous avons commencé à utiliser des crochets pour échapper les mots clés, nous avons perdu la possibilité de le faire. Dans la plupart des cas, cependant, ce n'est pas trop une limitation.
Pour être vraiment technique, x! Y fonctionne si x a une propriété par défaut qui prend une chaîne ou un objet comme paramètre. Dans ce cas, x! Y est changé en x.DefaultProperty ("y"). Une note intéressante est qu'il existe une règle spéciale dans la grammaire lexicale de la langue pour que tout cela fonctionne. Le ! Le caractère est également utilisé comme caractère de type dans la langue, et les caractères de type sont mangés avant les opérateurs. Ainsi, sans règle spéciale, x! Y serait scanné en "x! Y" au lieu de "x! Y". Heureusement, puisqu'il n'y a pas de place dans la langue où deux identifiants consécutifs sont valides, nous venons d'introduire la règle selon laquelle si le caractère suivant après le! est le début d'un identifiant, nous considérons le! être un opérateur et non un caractère de type.
Ceci est intégré et constitue un avantage certain sur C #. La possibilité d'implémenter une méthode d'interface sans avoir à utiliser le même nom.
Tel que:
Public Sub GetISCSIAdmInfo(ByRef xDoc As System.Xml.XmlDocument) Implements IUnix.GetISCSIInfo
End Sub
Forçage de ByVal
Dans VB, si vous encapsulez vos arguments dans un jeu de parenthèses supplémentaire, vous pouvez remplacer la déclaration ByRef de la méthode et la transformer en ByVal. Par exemple, le code suivant produit 4, 5, 5 au lieu de 4,5,6
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim R = 4
Trace.WriteLine(R)
Test(R)
Trace.WriteLine(R)
Test((R))
Trace.WriteLine(R)
End Sub
Private Sub Test(ByRef i As Integer)
i += 1
End Sub
Voir Argument non modifié par l'appel de procédure - Variable sous-jacente
Passer des paramètres par nom et donc les réorganiser
Sub MyFunc(Optional msg as String= "", Optional displayOrder As integer = 0)
'Do stuff
End function
Usage:
Module Module1
Sub Main()
MyFunc() 'No params specified
End Sub
End Module
Peut également être appelé à l'aide de la spécification du paramètre ": =" dans n'importe quel ordre:
MyFunc(displayOrder:=10, msg:="mystring")
L'instruction Using est nouvelle depuis VB 8, C # l'avait depuis le début. Elle appelle dispose automatiquement pour vous.
Par exemple.
Using lockThis as New MyLocker(objToLock)
End Using
Si vous avez besoin d'un nom de variable pour correspondre à celui d'un mot-clé, mettez-le entre crochets. Pas nec. la meilleure pratique cependant - mais elle peut être utilisée à bon escient.
par exemple.
Class CodeException
Public [Error] as String
''...
End Class
''later
Dim e as new CodeException
e.Error = "Invalid Syntax"
par exemple. Exemple de commentaires (@Pondidum):
Class Timer
Public Sub Start()
''...
End Sub
Public Sub [Stop]()
''...
End Sub
Les alias d'importation sont également largement inconnus:
Import winf = System.Windows.Forms
''Later
Dim x as winf.Form
Considérez la déclaration d'événement suivante
Public Event SomethingHappened As EventHandler
En C #, vous pouvez rechercher des abonnés aux événements à l'aide de la syntaxe suivante:
if(SomethingHappened != null)
{
...
}
Cependant, le compilateur VB.NET ne prend pas en charge cela. Il crée en fait un champ de membre privé caché qui n'est pas visible dans IntelliSense:
If Not SomethingHappenedEvent Is Nothing OrElse SomethingHappenedEvent.GetInvocationList.Length = 0 Then
...
End If
Plus d'information:
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
Il y a quelques réponses sur les littéraux XML, mais pas sur ce cas spécifique:
Vous pouvez utiliser des littéraux XML pour inclure des littéraux de chaîne qui devraient autrement être échappés. Les littéraux de chaîne contenant des guillemets doubles, par exemple.
Au lieu de cela:
Dim myString = _
"This string contains ""quotes"" and they're ugly."
Tu peux le faire:
Dim myString = _
<string>This string contains "quotes" and they're Nice.</string>.Value
Ceci est particulièrement utile si vous testez un littéral pour l'analyse CSV:
Dim csvTestYuck = _
"""Smith"", ""Bob"", ""123 Anywhere St"", ""Los Angeles"", ""CA"""
Dim csvTestMuchBetter = _
<string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value
(Vous n'avez pas besoin d'utiliser le <string>
tag, bien sûr; vous pouvez utiliser n'importe quelle balise que vous aimez.)
Vous pouvez avoir 2 lignes de code sur une seule ligne. Par conséquent:
Dim x As New Something : x.CallAMethod
DateTime peut être initialisé en entourant votre date de #
Dim independanceDay As DateTime = #7/4/1776#
Vous pouvez également utiliser l'inférence de type avec cette syntaxe
Dim independanceDay = #7/4/1776#
C'est beaucoup plus agréable que d'utiliser le constructeur
Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
Paramètres facultatifs
Les options sont tellement plus faciles que de créer de nouvelles surcharges, telles que:
Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
Console.Writeline(msg)
''//do stuff
End Function
Empiler/grouper plusieurs en utilisant des instructions ensemble:
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
Pour être juste, vous pouvez aussi le faire en C #. Mais beaucoup de gens ne le savent pas dans les deux langues.
Le cas de titre dans VB.Net peut être atteint par un ancien fxn VB6:
StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
Propriétés avec paramètres
J'ai fait de la programmation C # et j'ai découvert une fonctionnalité qui manquait à VB.Net, mais qui n'était pas mentionnée ici.
Un exemple de la façon de procéder (ainsi que la limitation c #) peut être vu à: tilisation des propriétés get set typiques en C # ... avec des paramètres
J'ai extrait le code de cette réponse:
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
L'une des fonctionnalités que j'ai trouvées très utiles et qui a aidé à résoudre de nombreux bogues est de passer explicitement des arguments aux fonctions, en particulier lors de l'utilisation facultative.
Voici un exemple:
Public Function DoSomething(byval x as integer, optional y as boolean=True, optional z as boolean=False)
' ......
End Function
alors vous pouvez l'appeler comme ceci:
DoSomething(x:=1, y:=false)
DoSomething(x:=2, z:=true)
or
DoSomething(x:=3,y:=false,z:=true)
C'est beaucoup plus propre et sans bug, puis appeler la fonction comme ceci
DoSomething(1,true)
Notez l'utilisation de when
dans la ligne 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
Vu récemment dans VbRad
Si vous n'avez jamais su ce qui suit, vous ne croirez vraiment pas que c'est vrai, c'est vraiment quelque chose qui manque à C #:
(Cela s'appelle des littéraux XML)
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}", customer.@id, 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 field.@type IsNot Nothing
Select
Name = field.@name,
Type = field.@type
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
Jetez un oeil à XML Literals Tips/Tricks par Beth Massi.
Vous pouvez avoir un If sur une ligne.
If True Then DoSomething()
Voici un drôle que je n'ai pas vu; Je sais que cela fonctionne dans VS 2008, au moins:
Si vous terminez accidentellement votre VB avec un point-virgule, parce que vous avez fait trop de C #, le point-virgule est automatiquement supprimé. Il est en fait impossible (encore une fois, dans VS 2008 au moins) de terminer accidentellement une ligne VB avec un point-virgule. Essayez-le!
(Ce n'est pas parfait; si vous tapez le point-virgule à mi-chemin de votre nom de classe final, il ne remplira pas automatiquement le nom de la classe.)
Contrairement à break
dans les langages C en VB vous pouvez Exit
ou Continue
le bloc que vous voulez:
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"))
Quel est le résultat? deux boîtes de message !!!! Cela se produit car la fonction IIf évalue les deux paramètres lorsqu'elle atteint la fonction.
VB a un nouvel opérateur If (tout comme C #?: Operator):
If(False, MsgBox("msg1"), MsgBox("msg2"))
N'affichera que la deuxième msgbox.
en général, je recommanderais de remplacer tous les IIF dans votre code vb, à moins que vous ne vouliez qu'il évoque les deux éléments:
Dim value = IIf(somthing, LoadAndGetValue1(), LoadAndGetValue2())
vous pouvez être sûr que les deux valeurs ont été chargées.
Vous pouvez utiliser un mot clé réservé pour les propriétés et les noms de variable si vous entourez le nom de [et]
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
Semblable à réponse de Parsa , le comme opérateur a beaucoup de choses sur lesquelles il peut correspondre et au-dessus de simples caractères génériques. J'ai failli tomber de ma chaise en lisant le doco MSDN dessus :-)
Dans VB8 et les anciennes versions, si vous n'avez spécifié aucun type pour la variable que vous introduisez, le type d'objet a été automatiquement détecté. Dans VB9 (2008), le Dim
agirait comme le mot clé var
de C # si l'option Infer est définie sur On (ce qui est, par défaut)
Sélectionnez Case au lieu de plusieurs instructions If/ElseIf/Else.
Supposons des objets géométriques simples dans cet exemple:
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
Lors de la déclaration d'un tableau dans vb.net, utilisez toujours la syntaxe "0 à xx".
Dim b(0 to 9) as byte 'Declares an array of 10 bytes
Cela rend très clair l'étendue du tableau. Comparez-le avec l'équivalent
Dim b(9) as byte 'Declares another array of 10 bytes
Même si vous savez que le deuxième exemple se compose de 10 éléments, cela ne semble pas évident. Et je ne me souviens pas du nombre de fois où j'ai vu du code d'un programmeur qui voulait ce qui précède mais a écrit à la place
Dim b(10) as byte 'Declares another array of 10 bytes
C'est bien sûr complètement faux. Comme b(10) crée un tableau de 11 octets. Et il peut facilement provoquer des bugs car il semble correct à quiconque ne sait pas quoi chercher.
La syntaxe "0 à xx" fonctionne également avec ce qui suit
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
En utilisant la syntaxe complète, vous montrerez également à quiconque lira votre code à l'avenir que vous saviez ce que vous faisiez.
Contrairement à C #, dans VB vous pouvez compter sur les valeurs par défaut pour les éléments non nullables:
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
Alors qu'en C #, ce sera une erreur de compilation:
int x;
var y = x.ToString(); //Use of unassigned value
Il est également important de se rappeler que les projets VB.NET, par défaut, ont un espace de noms racine qui fait partie des propriétés du projet. Par défaut, cet espace de noms racine aura le même nom que le projet. Lorsque vous utilisez la structure de bloc d'espace de noms, les noms sont en fait ajoutés à cet espace de noms racine. Par exemple: si le projet est nommé MyProject, alors nous pourrions déclarer une variable comme:
Private obj As MyProject.MyNamespace.MyClass
Pour modifier l'espace de noms racine, utilisez l'option de menu Projet -> Propriétés. L'espace de noms racine peut également être effacé, ce qui signifie que tous les blocs d'espace de noms deviennent le niveau racine du code qu'ils contiennent.
Le mot clé MyClass fournit un moyen de faire référence aux membres d'instance de classe tels qu'ils ont été implémentés à l'origine, en ignorant les remplacements de classe dérivés.
Le mot clé Nothing peut signifier default (T) ou null, selon le contexte. Vous pouvez exploiter cela pour créer une méthode très intéressante:
'''<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
Espaces de noms Aliassing
Imports Lan = Langauge
Bien qu'il ne soit pas unique à VB.Net, il est souvent oublié lors de l'exécution de conflits d'espace de noms.
VB propose également l'instruction OnError. Mais ce n'est pas très utile de nos jours.
On Error Resume Next
' Or'
On Error GoTo someline
</code>
Vous pouvez utiliser REM pour commenter une ligne au lieu de '. Pas super utile, mais aide les commentaires importants à se démarquer sans utiliser "!!!!!!!" ou autre.
Dates nulles! Ceci est particulièrement utile dans les cas où des données entrent/sortent d'une base de données (dans ce cas, MSSQL Server). J'ai deux procédures pour me donner un paramètre SmallDateTime, rempli avec une valeur. L'un d'eux prend une vieille date simple et teste pour voir s'il y a une valeur en lui attribuant une date par défaut. L'autre version accepte une Nullable(Of Date)
afin que je puisse laisser la date sans valeur, en acceptant la valeur par défaut de la procédure stockée
<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
Dans cet extrait, vous avez 2 (peut-être plus?) Choses que vous ne pourriez jamais faire en C #:
De plus, en C #, vous ne pouvez pas utiliser la fonctionnalité attendue sur l'objet - en C #, vous pouvez en rêver (maintenant, ils ont créé le mot-clé dynamique, mais c'est loin de VB). En C #, si vous écrirez (new object ()). Enabled vous obtiendrez une erreur indiquant que type object n'a pas de méthode 'Enabled'. Maintenant, je ne suis pas celui qui vous recommandera si c'est sûr ou non, les informations sont fournies TELLES QUELLES, faites par vous-même, bus encore, parfois (comme lorsque vous travaillez avec des objets COM) c'est une si bonne chose. Personnellement, j'écris toujours (expéditeur en tant que bouton) lorsque la valeur attendue est sûrement un bouton.
En fait d'ailleurs: prenez cet exemple:
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
Il n'est pas possible d'implémenter explicitement des membres d'interface dans VB, mais il est possible de les implémenter avec un nom différent.
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
Veuillez voter pour cette fonctionnalité sur Microsoft Connect .
Je ne sais pas à quel point vous pourriez l'appeler, mais l'opérateur If
pourrait compter.
C'est très similaire, en quelque sorte, au ?:
(ternaire) ou ??
opérateur dans de nombreux langages de type C. Cependant, il est important de noter qu'il évalue tous les paramètres, il est donc important de ne pas passer quoi que ce soit qui puisse provoquer une exception (sauf si vous le souhaitez) ou tout ce qui peut provoquer des effets secondaires involontaires.
Usage:
Dim result = If(condition, valueWhenTrue, valueWhenFalse)
Dim value = If(obj, valueWhenObjNull)
J'aimais beaucoup les paramètres de fonction facultatifs, mais je les utilise moins maintenant que je dois faire des allers-retours entre C # et VB beaucoup. Quand C # les prendra-t-il en charge? C++ et même C les avait (en quelque sorte)!
Différences entre ByVal et ByRef mots-clés:
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
Documentation du code
''' <summary>
'''
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub
Les utilisateurs de Someday Basic n'ont introduit aucune variable. Ils les ont présentés simplement en les utilisant. L'option explicite de VB a été introduite juste pour vous assurer que vous n'introduirez aucune variable par erreur en tapant mal. Vous pouvez toujours le désactiver, découvrez les jours où nous avons travaillé avec Basic.
Arguments optionnels à nouveau!
Function DoSmtg(Optional a As string, b As Integer, c As String)
'DoSmtg
End
' Call
DoSmtg(,,"c argument")
DoSmtg(,"b argument")
Attributs pour les méthodes! Par exemple, une propriété qui ne devrait pas être disponible au moment du design peut être 1) cachée de la fenêtre des propriétés, 2) non sérialisée (particulièrement gênante pour les contrôles utilisateur ou pour les contrôles chargés à partir d'une base de données):
<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
Mettre la DebuggerStepThrough()
est aussi très utile si vous faites un débogage (notez que vous pouvez toujours mettre un point d'arrêt dans la fonction ou autre chose, mais que vous pouvez ' t en une seule étape dans cette fonction).
De plus, la possibilité de mettre les choses en catégories (par exemple, "Données") signifie que, si vous voulez que la propriété apparaisse dans l'outil des propriétés -window, cette propriété particulière apparaîtra dans cette catégorie.
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