web-dev-qa-db-fra.com

Caractéristiques cachées de VB.NET?

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?

121
Sean Gough

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
128
torial

Enums 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.

/ÉDITER:

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.

82
Konrad Rudolph

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

Typedefs

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)
48
Konrad Rudolph

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>
45
Nescio

L'initialisation des objets est là aussi!

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

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:

  • Déballage d'un type de valeur, et
  • upcasting dans la hiérarchie des classes.

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? )

38
Konrad Rudolph

If opérateur conditionnel et coalescent

Je 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)
37
Konrad Rudolph

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
32
torial

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 #

31
cjk

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!

31
Jasha87
  • Opérateurs logiques AndAlso/OrElse

(EDIT: En savoir plus ici: Dois-je toujours utiliser les opérateurs AndAlso et OrElse? )

26
Joel Coehoorn

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

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.

25
Joel Coehoorn

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:

  • My.Computer: Accès aux informations liées à l'ordinateur telles que le système de fichiers, le réseau, les périphériques, les informations système, etc. Il donne accès à un certain nombre de ressources très importantes, notamment My.Computer.Network, My .Computer.FileSystem et My.Computer.Printers.
  • My.Application: Accès aux informations relatives à l'application particulière telles que nom, version, répertoire courant, etc.
  • My.User: Accès aux informations relatives à l'utilisateur authentifié actuel.
  • My.Resources: Accès aux ressources utilisées par l'application résidant dans des fichiers de ressources de manière fortement typée.
  • My.Settings: Accès aux paramètres de configuration de l'application de manière fortement typée.
23
splattne

Événements personnalisés

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
23
Konrad Rudolph

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.

21
torial

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
19
torial

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

17
Chris Haas

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

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
15
torial

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
14
torial

Les alias d'importation sont également largement inconnus:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form
14
torial

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

14
Technobabble

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.)

13
Ryan Lundy

Vous pouvez avoir 2 lignes de code sur une seule ligne. Par conséquent:

Dim x As New Something : x.CallAMethod
12
Parsa

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)
12
danlash

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
11
dr. evil

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.

9
Joel Coehoorn

Le cas de titre dans VB.Net peut être atteint par un ancien fxn VB6:

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

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
9
torial

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)
8
Youssef

Gestion des erreurs raffinée avec When

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

7
Eduardo Molteni

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.

7
Shimmy

Vous pouvez avoir un If sur une ligne.

If True Then DoSomething()
7
Parsa
  • Les espaces de noms enfants sont dans la portée après l'importation de leur parent. Par exemple, plutôt que d'avoir à importer System.IO ou dire System.IO.File pour utiliser la classe File, vous pouvez simplement dire IO.File. C'est un exemple simple: il y a des endroits où la fonctionnalité est vraiment utile, et C # ne le fait pas.
7
Joel Coehoorn

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.)

6
Ryan Lundy

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
6
Parsa
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.

5
Shimmy

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

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

5
Dan F

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)

5
Parsa

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
5
Clif

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.

5
Marcus Andrén

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

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.

4
Nescio

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.

4
Parsa

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
4
Craig Gidney

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.

3
chrissie1

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>
3
Parsa

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.

2
Booji Boy

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
2
David T. Macknet
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 #:

  1. Poignées Button1.Click - attachez un gestionnaire à l'événement en externe!
  2. L'implicitness de VB vous permet de déclarer le premier paramètre du gestionnaire comme type expexted. en C #, vous ne pouvez pas adresser un délégué à un modèle différent, même s'il s'agit du type attendu.

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

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 .

2
Parsa

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)
2
Sam Erwin

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)!

1
Joel Coehoorn

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

Documentation du code

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

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.

1
Parsa

Arguments optionnels à nouveau!

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

' Call
DoSmtg(,,"c argument")

DoSmtg(,"b argument")
0
Hedi Guizani

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.

0
David T. Macknet
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