Using und globale Variable

  • VB.NET

Es gibt 40 Antworten in diesem Thema. Der letzte Beitrag () ist von Storch.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private f2 As Form2
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. Using f2 As New Form2 With {.Text = "lokal"}
    5. MessageBox.Show((Me.f2 Is Nothing).ToString())
    6. MessageBox.Show((f2 Is Nothing).ToString())
    7. End Using
    8. End Sub
    9. End Class


    Sollte nun klar sein. Kopieren, probieren.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Hier ist nochmal ein Zitat:
    Überdeckung

    Oben hieß es schon, dass der Name einer Variablen innerhalb ihres Geltungsbereichs eindeutig sein muss. Was bedeutet das aber, wenn es innerhalb einer Klasse eine Variable gibt und in einer Methode eine neue Variable den gleichen Namen bekommt? Dann gilt:

    Die lokale Variable überdeckt die Variable aus dem umfassenden Bereich und hat Vorrang.

    Ändern wir das vorstehende Beispiel:

    VB.NET-Quellcode

    1. string temp = "Ein zweiter Versuch";
    2. for(int x1 = 0; x1 < 10; x1++ )
    3. {
    4. string temp = arr[x1];
    5. }


    Innerhalb der Schleife gibt es eine weitere Variable namens temp (und zwar weiterhin in jedem Durchgang eine neue). Innerhalb der Schleife kann aber nicht auf den Wert der außerhalb deklarierten temp-Variablen zugegriffen werden.


    de.wikibooks.org/wiki/Arbeiten…n/_Bestandteile/_Variable

    SpaceyX schrieb:

    Sollte nun klar sein. Kopieren, probieren.

    Ok nun ergibt es Sinn. Dann ist es aber in meinen Augen ein Bug von Visual Studio (2008 hab grad kein anderes zur Hand), dass die Private p so angezeigt wird als hätte sich eine Referenz auf das gleiche Objekt.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Wieso soll es ein Bug sein? Es wird eine Variable mit einem Namen angezeigt, der Programmierer sollte schon wissen, was er tut, wenn er schon eine lokale Variable mit dem gleichen Namen wie eine globale verwendet. Dann sollte er auch wissen, wo sie Gültigkeit hat.
    Ich finde eine IDE sollte eben genau solche Sachen korrekt anzeigen. Ist schon klar, dass ein Programmierer wissen muss was er tut, jedoch verlässt sich dieser auch gerne mal auf seine IDE. Wenn die dann so etwas anzeigt find ich es etwas "verwirrend".

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    @fichz:

    Ich weiß schon, was Du meinst. Das ist in der Tat sehr verwirrend. Ist in der 2012er Version genau das Selbe. Darum sollte man eben vermeiden, dass 2 Variablen, die sich den gleichen Scope teilen, die selben Namen haben. Für global deklarierte Variablen nutze ich stets ein "_" als Präfix. Ob es nun ein Bug oder so gewollt ist, kann ich auch nicht beurteilen. Am besten, man begibt sich nicht in eine solche Situation.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    So ich hab mir das mal ein wenig aufbereitet:

    VB.NET-Quellcode

    1. Public Class frm_tests
    2. Private ul As frm_about
    3. Private Sub cbt_usinglocal_Click(sender As Object, e As EventArgs) Handles cbt_usinglocal.Click
    4. 'Dim ul As New frm_about
    5. 'ul.ShowDialog()
    6. Using ul As New frm_about
    7. ul.ShowDialog()
    8. End Using
    9. End Sub
    10. Private Sub cbt_usingglobal_Click(sender As Object, e As EventArgs) Handles cbt_usingglobal.Click
    11. 'ul = New frm_about
    12. 'ul.ShowDialog()
    13. Using ul = New frm_about
    14. ul.ShowDialog()
    15. End Using
    16. End Sub
    17. End Class


    Ich betrachte jetzt erst mal alles so, als ginge es nicht um das Using sondern um die Deklaration und Verwendung einer Variablen, so wie die auskommentierte Zeilen:

    Mit As deklariert man eine Variable als das, was man hinter As angibt. Ohne dem New könnte man wohl sagen, ul fungiert als Platzhalter. Erst die Verwendung des New würde der Privaten ul schon bei der Deklaration einen Wert zuweisen. Also ist die Private ul beim Start meines frm_tests = Nothing.

    Zitat aus Hilfe für Shadowing:
    Sie können eine Variable ausblenden, indem Sie ein Shadowing für sie durchführen, d. h., indem Sie sie mit einer gleichnamigen Variablen neu definieren.
    Genau das passiert nun in cbt_usinglocal_Click . Durch 'Dim ul As New frm_about, wird ul neu definiert, was sozusagen die Private ul außer Kraft gesetzt.
    Trotzdem nimmt sie ebenfalls den Wert an, der Lokal zugewiesen wird, was mir duchaus logisch erscheint

    in cbt_usingglobal tritt das Shadowing aber nicht in Kraft, denn 'ul = New frm_about ist keine neue Definition der Variable ul ,sondern es wird ihr lediglich ein neuer Wert zugewiesen. Definiert ist sie ja schon durch Private

    Ich sehe da keine Fehler in meiner Logik. Ich frage mich jetzt nur, nimmt die Verwendung von Using Einfluss auf die Deklarationen und Wertzuweisungen?????

    Ich habe meinen TestCode (Using-Variante) laufen lassen, nach jedem End Using ist die ul wieder Nothing. Gleiches in meiner eigentlichen Anwendung.

    Letztlich wird man sich ja auch für eine der beiden Varianten entscheiden. Anderseits.. da der Aufruf eines ShowDialogs keine neuerlichen Aufruf zulässt, solange ein Form durch ShowDialog offen ist, dürfte sich auch eine Mischform obiger Art nicht beißen.


    Edith: Ich habe eben Euren letzen Beiträge gelesen.....
    Es ging mir nicht ursächlich darum, eine Doppelbelegung von Variablen zu verwenden. Meine Intention war schon: Entweder Global / Oder Lokal. Aber nachdem ich Using mit lokaler Variable angewendet habe, wollte ich halt wissen, wie es mit globaler Variable ist. Aber nicht prinzipiell mit beiden gleichzeitig. Trotzdem eine interessante Diskussion.
    GUD Uwe

    :whistling: Wenn ich genau wüsste, was ich nicht weiß, dann wäre mein Wissen vollständig!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Storch“ ()

    Ich verwende den selben Präfix. Gerade in Klassen der 2008er wo man die Properties noch ganz schreiben musste, hies die Property p und die Priavate dazu _p.

    @Storch: Du benötigst die lokale Variable nicht.
    In deinem Code merkst du den Unterschied wenn du ein Me. vor die Variable setzte. Dann wird nämlich die als Private deklarierte ausgewertet, die aber eigentlich Nothing ist. (siehe [VB 2012] Using und globale Variable)

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten

    Storch schrieb:

    was sozusagen die Private ul außer Kraft gesetzt.
    Trotzdem nimmt sie ebenfalls den Wert an, der Lokal zugewiesen wird, was mir duchaus logisch erscheint

    Wie kommst du jetzt darauf? Das passiert eben nicht.

    Storch schrieb:

    in cbt_usingglobal tritt das Shadowing aber nicht in Kraft, denn 'ul = New frm_about ist keine neue Definition der Variable ul ,sondern es wird ihr lediglich ein neuer Wert zugewiesen. Definiert ist sie ja schon durch Private

    Da bin ich mir nicht sicher, ich weiß nicht, ob es einen Unterschied macht.

    Storch schrieb:

    Ich habe meinen TestCode (Using-Variante) laufen lassen, nach jedem End Using ist die ul wieder Nothing. Gleiches in meiner eigentlichen Anwendung.

    Wie schon gesagt, EINE "ul" ist Nothing, SpaceyX hat doch vorhin gezeigt, wie man explizit globale Variable abfragt (mit Me.ul), erst da kannst du sehen, welchen Wert sie hat.
    @Storch:

    Shadowing hat mit dem Thema hier nicht wirklich etwas zu tun. Das gehört in den Bereich Vererbung.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    Storch schrieb:

    in cbt_usingglobal tritt das Shadowing aber nicht in Kraft, denn 'ul = New frm_about ist keine neue Definition der Variable ul ,sondern es wird ihr lediglich ein neuer Wert zugewiesen. Definiert ist sie ja schon durch Private


    Ich habe es gerade ausprobiert, es ist egal ob du "As" schreibst oder nicht, "Infer On" erledigt es für dich, es wird also in jedem Fall eine neue Variable angelegt.
    nö - nicht ganz in jedem Fall:

    VB.NET-Quellcode

    1. Private frm As New Form
    2. Private Sub AnyMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles TestToolStripMenuItem.Click
    3. Using frm
    4. frm.ShowDialog()
    5. End Using
    6. Dim b = frm.IsDisposed 'True!
    7. End Sub
    So ist die Block-Logik (oder unlogik): Bei

    VB.NET-Quellcode

    1. Using frm = New Form
    ist frm eine Block-lokale Variable, und bei

    VB.NET-Quellcode

    1. Using frm
    wird die bereits gegebene frm-Variable verwendet.

    Richtig interessant wirds beim For i - Block:

    VB.NET-Quellcode

    1. For i = 0 To 22
    2. '...
    3. Next
    4. 'MessageBox.Show(i.ToString) 'compile-error, denn i ist nur block-lokal gültig
    5. Dim ii = 0
    6. For ii = 0 To 22
    7. '...
    8. Next
    9. MessageBox.Show(ii.ToString) 'output: 23


    Also das Thema ist "Gültigkeitsbereich" (alias "Scope"), und sowohl beim Thema Scope als auch beim Thema Vererbung gibts einen Abschattier-Effekt (Shadowing), was aber jeweils bisserl was anneres bedeutet.
    Es ging aber darum, dass

    VB.NET-Quellcode

    1. Using frm As New Form2

    und

    VB.NET-Quellcode

    1. Using frm=New Form2

    unterschiedliches sein sollen, und das ist bei Infer On nicht der Fall (Intellisense zeigt mir bei frm gleich "As Form2" dazu an).

    Aber gut zu wissen, dass mit einem

    VB.NET-Quellcode

    1. Using frm

    dann keine neue Variable angelegt wird (wofür auch immer man das brauchen soll).
    Mich wundert's, dass noch niemand auf die Idee gekommen ist, einfach ein Testprogramm zu dekompilieren:
    Original

    VB.NET-Quellcode

    1. Public Class Program
    2. Private Shared Bar As Foo
    3. Public Shared Sub Main()
    4. Test1()
    5. Test2()
    6. Test3()
    7. End Sub
    8. Private Shared Sub Test1()
    9. Bar = New Foo("Test1")
    10. Bar.DoStuff()
    11. Program.Bar.DoStuff()
    12. Bar.Dispose()
    13. Bar = Nothing
    14. End Sub
    15. Private Shared Sub Test2()
    16. Dim Bar As Foo
    17. Bar = New Foo("Test2")
    18. Bar.DoStuff()
    19. Program.Bar.DoStuff()
    20. Bar.Dispose()
    21. Bar = Nothing
    22. End Sub
    23. Private Shared Sub Test3()
    24. Using Bar = New Foo("Test3")
    25. Bar.DoStuff()
    26. Program.Bar.DoStuff()
    27. End Using
    28. End Sub
    29. Private Shared Sub Test4()
    30. Using Bar As New Foo("Test4")
    31. Bar.DoStuff()
    32. Program.Bar.DoStuff()
    33. End Using
    34. End Sub
    35. Class Foo
    36. Implements IDisposable
    37. Public InternalValue As String
    38. Public Sub New(NewValue As String)
    39. InternalValue = NewValue
    40. End Sub
    41. Public Sub DoStuff()
    42. Console.WriteLine(InternalValue)
    43. End Sub
    44. #Region "IDisposable Support"
    45. Private disposedValue As Boolean ' So ermitteln Sie überflüssige Aufrufe
    46. ' IDisposable
    47. Protected Overridable Sub Dispose(disposing As Boolean)
    48. If Not Me.disposedValue Then
    49. If disposing Then
    50. ' TODO: Verwalteten Zustand löschen (verwaltete Objekte).
    51. InternalValue = Nothing
    52. End If
    53. ' TODO: Nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalize() unten überschreiben.
    54. ' TODO: Große Felder auf NULL festlegen.
    55. End If
    56. Me.disposedValue = True
    57. End Sub
    58. ' TODO: Finalize() nur überschreiben, wenn Dispose(ByVal disposing As Boolean) oben über Code zum Freigeben von nicht verwalteten Ressourcen verfügt.
    59. 'Protected Overrides Sub Finalize()
    60. ' ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(ByVal disposing As Boolean) Bereinigungscode ein.
    61. ' Dispose(False)
    62. ' MyBase.Finalize()
    63. 'End Sub
    64. ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster richtig zu implementieren.
    65. Public Sub Dispose() Implements IDisposable.Dispose
    66. ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(ByVal disposing As Boolean) Bereinigungscode ein.
    67. Dispose(True)
    68. GC.SuppressFinalize(Me)
    69. End Sub
    70. #End Region
    71. End Class
    72. End Class

    IL
    Gekürzt auf's Wesentliche

    C-Quellcode

    1. .class Program
    2. {
    3. .field private static Foo Bar
    4. .method public static void Main ()
    5. {
    6. IL_0000: call void Program::Test1()
    7. IL_0005: call void Program::Test2()
    8. IL_000a: call void Program::Test3()
    9. IL_000f: ret
    10. }
    11. .method private static void Test1 ()
    12. {
    13. IL_0000: ldstr "Test1"
    14. IL_0005: newobj instance void Foo::.ctor(string)
    15. IL_000a: stsfld class Foo Program.Bar // Entspricht Zeile 21. Hier wird wie zu erwarten war, die globale Variable verwendet.
    16. IL_000f: ldsfld class Foo Program.Bar
    17. IL_0014: callvirt instance void Foo::DoStuff()
    18. IL_0019: ldsfld class Foo Program.Bar
    19. IL_001e: callvirt instance void Foo::DoStuff() // Logischerweise kein Unterschied zwischen "Bar.DoStuff()" und "Program.Bar.DoStuff()"
    20. IL_0023: ldsfld class Foo Program.Bar
    21. IL_0028: callvirt instance void Foo::Dispose()
    22. IL_002d: ldnull
    23. IL_002e: stsfld class Foo Program.Bar
    24. IL_0033: ret
    25. }
    26. .method private static void Test2 ()
    27. {
    28. // Das ist die lokale Variable aus Zeile 20.
    29. .locals init (
    30. [0] class Foo Bar
    31. )
    32. IL_0000: ldstr "Test2"
    33. IL_0005: newobj instance void Foo::.ctor(string)
    34. IL_000a: stloc.0 // Hier wird die lokale Variable verwendet. Auch wie zu erwarten.
    35. IL_000b: ldloc.0
    36. IL_000c: callvirt instance void Foo::DoStuff() // "Bar.DoStuff()" verwendet die lokale Variable.
    37. IL_0011: ldsfld class Foo Program.Bar
    38. IL_0016: callvirt instance void Foo::DoStuff() // "Program.Bar.DoStuff()" verwendet die globale Variable. Immer noch ganz normal.
    39. IL_001b: ldloc.0
    40. IL_001c: callvirt instance void Foo::Dispose()
    41. IL_0021: ldnull
    42. IL_0022: stloc.0
    43. IL_0023: ret
    44. }
    45. .method private static void Test3 () // Zwischen Test3 und Test4 besteht kein Unterschied (bis auf den String).
    46. {
    47. // Durch Using wird eine lokale Variable deklariert.
    48. .locals init (
    49. [0] class Foo Bar
    50. )
    51. IL_0000: ldstr "Test3"
    52. IL_0005: newobj instance void Foo::.ctor(string)
    53. IL_000a: stloc.0 // Die lokale Variable wird verwendet. Die globale Variable wird nicht angerührt.
    54. .try
    55. {
    56. IL_000b: ldloc.0
    57. IL_000c: callvirt instance void Foo::DoStuff() // Auch hier wird die lokale Variable verwendet.
    58. IL_0011: ldsfld class Foo Program.Bar
    59. IL_0016: callvirt instance void Foo::DoStuff() // "Program.Bar.DoStuff()" verwendet natürlich wieder die globale Variable.
    60. IL_001b: leave.s IL_0027
    61. }
    62. finally
    63. {
    64. IL_001d: ldloc.0
    65. IL_001e: brfalse.s IL_0026
    66. IL_0020: ldloc.0
    67. IL_0021: callvirt instance void [mscorlib]System.IDisposable::Dispose()
    68. IL_0026: endfinally
    69. }
    70. IL_0027: ret
    71. }
    72. .method private static void Test4 ()
    73. {
    74. .locals init (
    75. [0] class Foo Bar
    76. )
    77. IL_0000: ldstr "Test4"
    78. IL_0005: newobj instance void Foo::.ctor(string)
    79. IL_000a: stloc.0
    80. .try
    81. {
    82. IL_000b: ldloc.0
    83. IL_000c: callvirt instance void Foo::DoStuff()
    84. IL_0011: ldsfld class Foo Program.Bar
    85. IL_0016: callvirt instance void Foo::DoStuff()
    86. IL_001b: leave.s IL_0027
    87. }
    88. finally
    89. {
    90. IL_001d: ldloc.0
    91. IL_001e: brfalse.s IL_0026
    92. IL_0020: ldloc.0
    93. IL_0021: callvirt instance void [mscorlib]System.IDisposable::Dispose()
    94. IL_0026: endfinally
    95. }
    96. IL_0027: ret
    97. }
    98. }


    Fazit: Wie bereits richtig erklärt wurde, überdeckt eine lokale Variable eine globale vollständig.
    Bei Using wird eine neue, lokale Variable angelegt.


    Übrigens ist ein Using Block nicht einfach nur ein Dispose-Aufruf am Ende, sondern, wie man sieht, auch ein Try-Finally-Block.
    Dadurch wird sichergestellt, dass das Objekt auf jeden Fall verworfen wird. Auch, wenn eine Exception im Try-Block ausgelöst wird. Und natürlich wird noch überprüft, ob die lokale Variable nicht Nothing ist, da sonst ein Aufruf an die Disposed-Methode eine NullReferenceException auslösen würde.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Da soll nun noch einer durchsehen. :(

    Das Fazit, was aus allem jetzt ziehe ist:

    VB.NET-Quellcode

    1. Using frm As New Form2

    ist im Grunde das selbe wie wie

    VB.NET-Quellcode

    1. Using frm = New Form2

    denn, egal wie man es schreibt, es wird hier immer eine neue Variable erstellt, egal ob man As oder = schreibt. Für die lokale Variante scheint mir das dann egal zu sein. Aus Gewohnheit würde ich As schreiben.

    Global müsste dann also vorher die frm-Variable vollständig deklarieren und belegen:

    VB.NET-Quellcode

    1. Private frm As New Form2
    2. Using frm
    3. 'Mach Was
    4. End Using
    5. frm = Nothing

    Aber man müsste die Variable selbst nach End Using auf Nothing setzen, bei Bedarf.

    ????????????????????????????

    @Niko
    ich verstehe nicht, wie ich Deinen Code für mich nutzbar machen kann!!??
    GUD Uwe

    :whistling: Wenn ich genau wüsste, was ich nicht weiß, dann wäre mein Wissen vollständig!
    Using ist eiglich nur sinnvoll mit lokalen Variablen.
    Es ist zwar möglich, Using auch auf vor-initialisierte Variablen zu setzen, aber dassis extrem unüblich. Denn man erschafft ja vor-initialisierte Variablen genau aus dem Grund, dass man sie mehrmals benutzen will. Using ist aber so, dasses nur einmal used, und dann hauts den Kram weg.
    Bei letzterem musste auch nix auf Nothing setzen, denn nach verlassen des Using-Blocks ist die Variable eh aussm Scope raus, nicht mehr erreichbar, und also Fressen für den GC.

    Storch schrieb:

    Global müsste dann also vorher die frm-Variable vollständig deklarieren und belegen:

    VB.NET-Quellcode

    1. Private frm As New Form2
    2. Using frm
    3. 'Mach Was
    4. End Using
    5. frm = Nothing

    Aber man müsste die Variable selbst nach End Using auf Nothing setzen, bei Bedarf.

    Wie schon gesagt:

    sonne75 schrieb:

    Gut, das hat @SpaceyX: dann beantwortet:

    Zitat von »SpaceyX«
    Using kannst Du nur innerhalb eines Methodenrumpfes verwenden.



    Storch schrieb:

    @Niko
    ich verstehe nicht, wie ich Deinen Code für mich nutzbar machen kann!!??

    Für dich nicht, es hat gezeigt, wie intern mit dieser Problematik umgegangen wird: globale und lokale Variable mit gleichem Namen. Es war ein Beweis an "ungläubige" :P , dass es tatsächlich so ist.
    (Edit: Seit ich den Post angefangen habe, sind knappe 2 Stunden vergangen)

    @Storch:
    Garnicht. Es macht üblicherweise keinen Sinn, eine globale Variable (oder eine bereits deklarierte, lokale Variable) in einem Using-Block zu verwenden. Deshalb wird auch immer eine neue, lokale Variable angelegt.
    Der Sinn von Using ist ja, dass man lokal, für begrenzte Zeit, eine Ressource hat, die unbedingt wieder verworfen werden muss.
    Ein Beispiel:

    VB.NET-Quellcode

    1. Private Sub SaveToBitmap()
    2. Using Bpm As New Bitmap(Width, Height)
    3. Using g = Graphics.FromImage(Bpm) 'Der Unterschied besteht hier nur in der praktischeren Schreibweise
    4. g.DrawStuff()
    5. End Using
    6. Bpm.Save("C:\....")
    7. End Using
    8. End Sub

    Also wenn Du Using verwendest, musst Du weder irgendwas disposen noch auf Nothing setzen. (Und einfach keine bereits existierenden Variablen im Using-Block verwenden.)


    Edit 2:
    Um das Problem mit der globalen Variable zu erklären: Das ist ein Bug der IDE. Wenn man mit der Maus über den Namen einer Variable fährt, dann wird nicht die tatsächliche Variable angezeigt, sondern die relativ zur aktuellen Codezeile "lokalste" Variable mit diesem Namen, die gefunden wird.
    Beispiel:

    VB.NET-Quellcode

    1. Public Class Program
    2. Public Shared Sub Main()
    3. HasLocal()
    4. End Sub
    5. Private Shared Bar As Foo
    6. Private Shared Sub HasLocal()
    7. Dim Bar As New Foo("Local")
    8. HasNoLocalButArgumentInstead(Bar)
    9. End Sub
    10. Private Shared Sub HasNoLocalButArgumentInstead(Argument As Foo)
    11. Dim bp = 0
    12. End Sub
    13. Class Foo
    14. Public InternalValue As String
    15. Public Sub New(NewValue As String)
    16. InternalValue = NewValue
    17. End Sub
    18. End Class
    19. End Class

    Die globale Variable ist immer Nothing, aber wenn man bei Zeile 11 wartet (also noch nicht in die Methode hineingeht), dann wird bei beiden Bars das Objekt der lokalen Variable angezeigt. Sobald man aber bis Zeile 15 debuggt, ist Bar plötzlich wieder Nothing (auch die lokale Bar-Variable der HasLocal-Methode, obwohl man diese Variable eigentlich nicht sehen kann (kann man auch nicht, die IDE zeigt in Wirklichkeit die globale Variable an). Stattdessen bekommt man das Objekt der lokalen Variable über das Argument.
    Macht man in der Aufrufliste einen Doppelklick auf die HasLocal-Methode, hat man wieder den Zustand von vorhin.

    Und deshalb, meine Freunde, gibt man Variablen möglichst eindeutige Namen.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Niko Ortner“ ()