Frage

Bei der Arbeit, arbeite ich häufig auf Projekte, bei denen zahlreiche Eigenschaften bestimmter Objekte im Bau befindlichen oder früh im Laufe ihres Lebens eingestellt werden. Aus Gründen der Bequemlichkeit und Lesbarkeit, verwende ich oft die With Anweisung, diese Eigenschaften zu setzen. Ich finde, dass

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

Sieht viel besser als

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

für sehr lange Aussagen, die nur Eigenschaften festgelegt.

Ich habe bemerkt, dass es einige Probleme bei der Verwendung With beim Debuggen sind; jedoch Ich habe mich gefragt, ob es zwingende Gründe waren mit With in der Praxis zu vermeiden ? Ich habe immer angenommen, der Code über den Compiler für die beiden oben genannten Fällen erzeugt ist im Grunde das gleiche, weshalb ich immer gewählt haben, zu schreiben, was ich fühle mich besser lesbar zu sein.

War es hilfreich?

Lösung

Wenn Sie lange variablenames und würde am Ende mit:

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

dann würde ich verwenden, um sie besser lesbar zu machen:

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

Im späteren Beispiel gibt es sogar Performance-Vorteil gegenüber dem ersten Beispiel, weil in dem ersten Beispiel im dem Benutzer jedes Mal holt mir eine Benutzereigenschaft zuzugreifen und diese in dem WITH-Fall, den ich nur die Benutzer einmal holen.

Ich kann die Performance-Gewinn erhalten, ohne mit, wie folgt aus:

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"

Aber ich würde für die WITH-Anweisung geht stattdessen sieht es sauberer.

Und ich habe gerade dies als Beispiel so nicht eine Klasse klagt über mit vielen Keywords, könnte ein weiteres Beispiel wie: MIT RefundDialog.RefundDatagridView.SelectedRows (0)

Andere Tipps

In der Praxis gibt es keine wirklich überzeugenden Punkte dagegen. Ich bin kein Fan, aber das ist eine persönliche Präferenz, gibt es keine empirischen Daten zu deuten darauf hin, dass das With Konstrukt ist schlecht.

In .NET kompiliert es zu genau der gleichen Code wie voll die Qualifikation der Objektname, so dass es keine Leistungseinbuße für diesen Zucker. Ich ermitteln dies durch Kompilieren, dann Zerlegen, die folgende VB .NET 2.0-Klasse:

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

Die Demontage ist wie folgt - beachten Sie, dass die Anrufe an sb2 des Append Methode zur With Anweisung identisch aussehen fordert 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

Also, wenn Sie es mögen, und finden es besser lesbar, gehen für sie; es gibt keinen zwingenden Grund, nicht zu.

(By the way, Tom , ich bin daran interessiert zu wissen, was mit dem Debugger passiert ist - ich kann‘ t Rückruf jemals eine ungewöhnliche Verhalten in dem auf einer With Aussage basiert Debugger zu sehen, so dass ich bin neugierig, zu wissen, welches Verhalten Sie nicht sehen.)

Es gibt einen Unterschied zwischen der Verwendung mit und machen sich wiederholende Verweise auf ein Objekt, das subtil ist, sollte aber nicht vergessen werden, denke ich.

Wenn eine MIT-Anweisung verwendet wird, erstellt er eine neue lokale Variable verweist auf das Objekt. Nachfolgende Referenzen mit .xx sind Verweise auf Eigenschaften des lokalen Referenz. Wenn während der Ausführung der Anweisung MIT, die ursprüngliche variable Referenz geändert wird, verweist die Aufgabe durch die MIT nicht ändert. Bedenken Sie:

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

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

So ist die WITH-Anweisung nicht einfach syntaktischer Zucker, es ist wirklich ein anderes Konstrukt. Während Sie wäre unwahrscheinlich, dass etwas explizit wie die oben codieren, in einigen Situationen dies versehentlich auftreten könnten, so sollten Sie sich des Problems bewusst sein. Die wahrscheinlichste Situation ist, wo Sie eine Struktur wie ein Netzwerk von Objekten, der Verbindungen meint, indem Eigenschaften implizit geändert werden können, werden durchlaufen.

Es geht um die Lesbarkeit. Wie alle syntaktischen Zucker, kann es sein, überstrapaziert .

es Umfassen IF sind Sie mehrere Mitglieder eines Objekts über ein paar Zeilen

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

Vermeiden etwas anderes zu tun mit "mit"

Wenn Sie schreiben ein Mit-Block, der 50 bis 100 Linien und beinhaltet viele andere Variablen reicht es wirklich schwierig machen kann zu erinnern, was an der Spitze des Blocks erklärt wurde. Aus offensichtlichen Gründen werde ich ein Beispiel eines solchen unordentlichen Code nicht liefern

Wenn es der Code wirklich besser lesbar macht, gehen für sie. Wo es macht es weniger lesbar, es vermeiden -. Insbesondere, empfehle ich Ihnen vermeiden Mit Aussagen nisten

C # 3.0 hat diese Funktion nur für Objektinitialisierung:

var x = new Whatever { PropertyA=true, PropertyB="Inactive" };

Dies ist nicht nur ziemlich viel für LINQ erforderlich, aber es macht auch Sinn, in Hinblick darauf, wo die Syntax nicht einen Code Geruch anzeigt. Ich in der Regel feststellen, dass, wenn ich viele verschiedene Operationen für ein Objekt jenseits seiner ursprünglichen Konstruktion Durchführung bin, sollen diese Operationen als einzige auf dem Objekt selbst verkapselt werden.

Eine Anmerkung zu Ihrem Beispiel - brauchen Sie wirklich die „Me“ überhaupt? Warum nicht einfach schreiben:

PropertyA = True
PropertyB = "Inactive"

? Sicher "Me" ist in diesem Fall impliziert ...

würde ich misstrauisch Code sein, der eine Menge dieses Schlüsselwort verwendet: wenn es verwendet wird, um leichter zu machen viele Instanzvariablen oder Eigenschaften festlegen ich denke, das kann darauf hindeuten, dass Ihre Klassen zu groß sind ( große Klasse Geruch ). Wenn Sie es verwenden, lange Ketten von Anrufen wie folgt zu ersetzen:

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"

dann sind Sie wahrscheinlich zu verletzen Demeter Law

Ich benutze keine VB.NET (I verwenden Ebene VB verwenden), aber ...

Ist der führende Punkt obligatorisch? Wenn ja, dann sehe ich kein Problem. In Javascript, ist das Ergebnis with die Verwendung, dass eine Eigenschaft eines Objekts als eine einfache Variable genauso aussieht, und , die ist sehr gefährlich, da Sie nicht sehen, wenn Sie eine Immobilie zuzugreifst oder eine Variable, und somit with ist etwas zu vermeiden.

Es ist nicht nur seine Verwendung auf die Augen leichter, aber für den wiederholten Zugriff auf die Eigenschaften eines Objekts, ist es wahrscheinlich schneller sein, da das Objekt nur durch die Methode Kette einmal abgerufen wird, und nicht einmal für jede Eigenschaft.

mich mit anderen Antworten einverstanden, dass Sie sollten verschachtelte Verwendung von with, aus dem gleichen Grunde zu vermeiden, wie warum with insgesamt in Javascript zu vermeiden. Weil Sie nicht mehr sehen, was Ihre Immobilie Objekt gehört

Die ‚mit‘ ist im Grunde die ‚Kaskade‘ von Smalltalk. Es ist ein Muster in Kent Becks Smalltalk Best Practice Patterns Buch.

Eine Zusammenfassung der Muster: es verwendet, wenn es sinnvoll, Gruppe auf das Objekt gesendet, die Nachrichten macht. Verwenden Sie es nicht, wenn es passiert nur einige Nachrichten auf das gleiche Objekt gesendet werden.

Vermeiden Sie die mit dem Block um jeden Preis (auch Lesbarkeit). Zwei Gründe:

  1. Microsoft Dokumentation über With ... End With sagt, dass unter bestimmten Umständen, erstellt es eine Kopie der Daten auf dem Stack, so dass alle Änderungen, die Sie weggeworfen werden machen.
  2. Wenn Sie es für LINQ-Abfragen verwenden, führen Sie die Lambda-Ergebnisse NICHT Kette und so jedes Ergebnis der Zwischen-Klausel wird weggeworfen.

Um dies zu beschreiben, haben wir ein (gebrochen) Beispiel aus einem Lehrbuch, das meine Mitarbeiter hatten den Autor fragen (es tatsächlich falsch ist, haben die Namen geändert zu schützen ... was auch immer):

  

Mit dbcontext.Blahs
    .OrderBy (Funktion (currentBlah) currentBlah.LastName)
    .ThenBy (Funktion (currentBlah) currentBlah.FirstName)
    .Load ()
  Mit

Die OrderBy und ThenBy haben No Effect überhaupt. Wenn Sie den Code, indem nur den mit dropping und End With, und das Hinzufügen von Zeilenfortsetzungszeichen am Ende der ersten drei Zeilen umformatieren ... es funktioniert (wie dargestellt 15 Seiten später in dem gleichen Lehrbuch) .

Wir brauchen nicht mehr Grund zu suchen und zerstören mit Blöcken. Sie hatten nur in einem Ausgelegt Rahmen Bedeutung.

Es gibt eine Gotcha, wenn es mit Strukturen verwendet, auch bekannt als Sie nicht ihre Felder festlegen können, da Sie auf einer lokalen Kopie arbeiten (zum Zeitpunkt des Eintritts in mit Block gemacht) der „mit“ Ausdruck und arbeitet nicht mit a (Kopie eines) Objektverweis in diesem Fall:

  

Der Datentyp objectExpression kann jede Klasse oder Struktur-Typ sein   oder sogar ein Visual Basic elementarer Typ wie Integer. Wenn   objectExpression ergibt sich etwas anderes als ein Objekt, können Sie   Lesen nur die Werte seiner Mitglieder oder Methoden aufrufen, und Sie erhalten eine   Fehler, wenn Sie versuchen, Werte für die Mitglieder einer Struktur in einem benutzten zuweisen   Mit ... End With-Anweisung. Dies ist der gleiche Fehler, den Sie, wenn Sie bekommen würde   eine Methode aufgerufen, die eine Struktur und sofort zugegriffen zurückgegeben   und einen Wert für ein Mitglied des Funktionsergebnisses zugeordnet ist, wie beispielsweise   GetAPoint (). X = 1. Das Problem ist in beiden Fällen, dass die Struktur   existiert nur auf den Call-Stack, und es gibt keine Möglichkeit, eine modifizierte   Strukturelement in diesen Situationen kann zu einer Stelle schreiben, so dass   ein anderer Code in dem Programm kann die Veränderung beobachten.

     

Die objectExpression wird einmal ausgewertet, bei Eintritt in den Block. Sie   kann nicht die objectExpression aus dem Block mit neu zuweisen.

https : //docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/with-end-with-statement

den Compiler erraten könnte etwas klüger, wenn Sie mit Anweisung, um einen Strukturnamen anstelle eines Ausdrucks übergeben wurden, um die eine Struktur zurückgibt, scheint aber es ist nicht

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top