71 votes

La déclaration "avec" de VB.NET - embrasser ou éviter?

Au travail, je suis souvent à travailler sur des projets où de nombreuses propriétés de certains objets doivent être définis lors de leur construction ou tôt au cours de leur vie. Pour plus de clarté et de lisibilité, j'utilise souvent l' With déclaration de définir ces propriétés. Je trouve que

With Me.Elements
    .PropertyA = True
    .PropertyB = "Inactive"
    ' And so on for several more lines
End With

Est beaucoup mieux que

Me.Elements.PropertyA = True
Me.Elements.PropertyB = "Inactive"
' And so on for several more lines

pour de très longues déclarations qui tout simplement définir les propriétés.

J'ai remarqué qu'il y a quelques problèmes avec l'utilisation de With pendant le débogage; cependant, je me demandais si il existait des raisons impérieuses d'éviter d'utiliser des With dans la pratique? J'ai toujours supposé que le code généré par le compilateur pour les deux cas ci-dessus est fondamentalement la même, c'est pourquoi j'ai toujours choisi d'écrire ce que je ressens pour être plus lisible.

69voto

Stefan Points 7940

Si vous avez longtemps variablenames et avec:

UserHandler.GetUser.First.User.FirstName="Stefan"
UserHandler.GetUser.First.User.LastName="Karlsson"
UserHandler.GetUser.First.User.Age="39"
UserHandler.GetUser.First.User.Sex="Male"
UserHandler.GetUser.First.User.Occupation="Programmer"
UserHandler.GetUser.First.User.UserID="0"
....and so on

alors je voudrais utiliser pour la rendre plus lisible:

With UserHandler.GetUser.First.User
    .FirstName="Stefan"
    .LastName="Karlsson"
    .Age="39"
    .Sex="Male"
    .Occupation="Programmer"
    .UserID="0"
end with

Dans le dernier exemple, il y a même l'avantage de performance au cours de la première exemple car dans le premier exemple de la Gi de l'extraction de l'utilisateur à chaque fois que je accéder à une propriété de l'utilisateur et dans la cas je ne récupérer l'utilisateur à un moment donné.

Je peux obtenir le gain de performance sans l'aide avec, comme ceci:

dim myuser as user =UserHandler.GetUser.First.User
myuser.FirstName="Stefan"
myuser.LastName="Karlsson"
myuser.Age="39"
myuser.Sex="Male"
myuser.Occupation="Programmer"
myuser.UserID="0"

Mais je voudrais aller AVEC l'instruction au lieu de cela, il semble plus propre.

Et j'ai juste pris un exemple afin de ne pas se plaindre sur une classe avec beaucoup de mots-clés, un autre exemple pourrait être: AVEC RefundDialog.RefundDatagridView.SelectedRows(0)

24voto

John Rudy Points 16436

Dans la pratique, il n'y a pas vraiment convaincante points contre elle. Je ne suis pas un fan, mais c'est une question de préférence personnelle, il n'y a pas de données empiriques suggèrent que l' With construire est mauvais.

Dans .NET, il compile pour exactement le même code que entièrement admissible, le nom de l'objet, donc il n'y a pas de pénalité sur les performances de ce sucre. J'ai constaté en compilant, puis le démontage, la suite de VB .NET 2.0 classe:

Imports System.Text

Public Class Class1
    Public Sub Foo()
        Dim sb As New StringBuilder
        With sb
            .Append("foo")
            .Append("bar")
            .Append("zap")
        End With

        Dim sb2 As New StringBuilder
        sb2.Append("foo")
        sb2.Append("bar")
        sb2.Append("zap")
    End Sub
End Class

Le démontage est comme suit: à noter que les appels à l' sb2s' Append méthode identique à l' With déclaration appels d' sb:

.method public instance void  Foo() cil managed
{
  // Code size       91 (0x5b)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.Text.StringBuilder sb,
           [1] class [mscorlib]System.Text.StringBuilder sb2,
           [2] class [mscorlib]System.Text.StringBuilder VB$t_ref$L0)
  IL_0000:  nop
  IL_0001:  newobj     instance void [mscorlib]System.Text.StringBuilder::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  stloc.2
  IL_0009:  ldloc.2
  IL_000a:  ldstr      "foo"
  IL_000f:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_0014:  pop
  IL_0015:  ldloc.2
  IL_0016:  ldstr      "bar"
  IL_001b:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_0020:  pop
  IL_0021:  ldloc.2
  IL_0022:  ldstr      "zap"
  IL_0027:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_002c:  pop
  IL_002d:  ldnull
  IL_002e:  stloc.2
  IL_002f:  newobj     instance void [mscorlib]System.Text.StringBuilder::.ctor()
  IL_0034:  stloc.1
  IL_0035:  ldloc.1
  IL_0036:  ldstr      "foo"
  IL_003b:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_0040:  pop
  IL_0041:  ldloc.1
  IL_0042:  ldstr      "bar"
  IL_0047:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_004c:  pop
  IL_004d:  ldloc.1
  IL_004e:  ldstr      "zap"
  IL_0053:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_0058:  pop
  IL_0059:  nop
  IL_005a:  ret
} // end of method Class1::Foo

Donc si vous le souhaitez, et de trouver plus lisible, allez-y; il n'y a aucune raison de ne pas l'.

(En passant, Tom, je suis intéressé à savoir ce qui s'est passé avec le débogueur -- je ne me souviens pas avoir déjà vu tout comportement inhabituel dans le débogueur basé sur un With déclaration, donc je suis curieux de savoir quel comportement vous fait voir.)

15voto

JohnRC Points 41

Il y a une différence entre l'utilisation Avec et faire répéter les références à un objet, ce qui est subtil mais il convient de garder à l'esprit, je pense.

Lorsqu'une instruction est utilisé, il crée une nouvelle variable locale faisant référence à l'objet. Les références ultérieures à l'aide .xx sont des références à des propriétés de la référence locale. Si lors de l'exécution de l'instruction, la variable d'origine de référence est modifié, l'objet référencé par la AVEC ne change pas. Considérer:

Dim AA As AAClass = GetNextAAObject()
With AA
    AA = GetNextAAObject()

    '// Setting property of original AA instance, not later instance
    .SomeProperty = SomeValue
End With

Ainsi, l'instruction n'est pas simplement du sucre syntaxique, il s'agit vraiment d'une autre structure. Alors que vous aurait peu de chances de code quelque chose d'explicite comme ci-dessus, dans certaines situations, cela pourrait se produire, par inadvertance, de sorte que vous devriez être au courant de la question. La situation la plus probable est l'endroit où vous pouvez être vous traversez une structure telle qu'un réseau d'objets dont les interconnexions mon être modifié implicitement par la définition des propriétés.

13voto

phillihp Points 62

Il est tout au sujet de la lisibilité. Comme tous les sucre syntaxique, il peut être galvaudé.

L'embrasser SI vous êtes l'établissement de plusieurs membres d'un objet de plus de quelques lignes

With myObject
  .Property1 = arg1
  .Property2 = arg2
...

Évitez de faire autre chose avec "Avec"

Si vous écrivez un bloc qui s'étend sur 50 à 100 lignes et implique de nombreuses autres variables, il peut être VRAIMENT difficile de se souvenir de ce qui a été déclaré au sommet du bloc. Pour des raisons évidentes, je ne vais pas fournir un exemple de code désordre

5voto

ljorquera Points 725

Je serait suspect de code qui utilise beaucoup ce mot-clé: si elle est utilisée pour les rendre plus faciles à mettre beaucoup de variables d'instance ou de propriétés, je pense que cela peut indiquer que vos classes sont trop grandes ( Grande Classe odeur ). Si vous l'utilisez pour remplacer de longues chaînes d'appels comme ceci:

UserHandler.GetUser.First.User.FirstName="Stefan"
UserHandler.GetUser.First.User.LastName="Karlsson"
UserHandler.GetUser.First.User.Age="39"
UserHandler.GetUser.First.User.Sex="Male"
UserHandler.GetUser.First.User.Occupation="Programmer"
UserHandler.GetUser.First.User.UserID="0"

alors vous êtes probablement à la violation de la Loi de Demeter

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X