Announcement

Collapse
No announcement yet.

Auswerten des Wertes NIL

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Auswerten des Wertes NIL

    Habe ein kleines Prob mit TListView. Wenn ich den Index dre Selektierten Zeile erfassen will und Klicke in die zweite Spalte, so bekomme ich eine EXception. Ich denke das in der Variablen Index der Wert nil steht anstelle von 0. Wie kann ich die Variable auf nil prüfen ?
    IF THEN geht nicht ::-(

  • #2
    Hallo

    Man kann mit assigned(var) prüfen ob der Wert nil ist

    Comment


    • #3
      Hallo Marcus;

      Die Function Assigned ist meiner Ansicht nach mit Vorsicht zu genießen.

      Warum !? - Nun schau Dir mal folgendes Beispiel an:

      <PRE>
      procedure TForm1.FormCreate(Sender: TObject);
      var Test: TObject;
      begin
      //Test:=nil;

      if assigned(Test)
      then ShowMessage('Test is Assigned')
      else ShowMessage('Test is not Assigned');
      end;
      </PRE>

      und danach dekommentierst Du mal die Zeile

      <PRE>
      Test:=nil;
      </PRE>

      Wie Du siehst, liefert die Function den Wert Assigned=True wenn die Variable Test nicht initialisiert wurde. Erst wenn Du der Variable den Wert Nil zuweißt, liefert Assigned - False;

      Gruß, To

      Comment


      • #4
        Richtig, damit ist Test <> nil, da Test nicht vorher initialisiert wurde. Dies ist kein Problem von Assigned oder anderen Auswertungen, sondern nur ein Problem des Programmierers da er die Daten uninitialisert benutzt <br>

        Hier noch einige Beispiele:

        <pre>

        var
        I: Integer;
        D: Double;
        S: ShortString;
        O: TObject;
        begin
        if I <> 0 then ;
        if D = 5.21 then ;
        if S = 'test' then ;
        if O = nil then ;
        end;<br>

        </pre>

        Gruß Hage

        Comment


        • #5
          Hallo Hagen,

          Bitte nimm es mir nicht übel, aber dieser Beitrag wurde im Kapitel Delphi-Neulinge eröffnet. Aus diesem Grund habe ich behauptet, das man die Funktion Assigned mit Vorsicht genießen sollte.

          Aber wo wir schon mal dabei sind; Es gibt immerhin auch die Möglichkeit, dass ein Object zuvor erstellt und danach wieder zerstört wurde. In diesem Fall liefert die Funktion Assigned ebenfalls True zurück.

          Wenn der Entwickler also eine Reihe von Objekten dynamisch erzeugt bzw. zerstört, und fragt irgendwann den Zustand der Objekte mit Assigned ab, könnte es zu sporadischen Exceptions kommen, wenn er versucht ein zerstörtes Object anzusprechen, dessen Zustand Ihm die Funktion Assigned mit True, also Zugewiesen bestätigt hat.

          Beispiel 2:
          <PRE>
          procedure TForm1.FormCreate(Sender: TObject);
          var Test: TObject;
          begin
          Test:=TObject.Create;

          if assigned(Test)
          then ShowMessage('Test is Assigned')
          else ShowMessage('Test is not Assigned');

          Test.Destroy;

          if assigned(Test)
          then ShowMessage('Test is Assigned')
          else ShowMessage('Test is not Assigned');

          Test:=nil;

          if assigned(Test)
          then ShowMessage('Test is Assigned')
          else ShowMessage('Test is not Assigned');
          end;
          </PRE>

          Bitte um Rückmeldung,

          Gruß, To

          Comment


          • #6
            Hallo Thomas,<p>
            es ist vielleicht nicht schlecht, daß diese Diskussion hier einmal geführt wird. Die Delphi-Hilfe enthält hier nämlich einen Fehler und verschweigt einfach einige Tatsachen. Wenn man mal unter TObject.Free in der Hilfe nachliest, so wird dort empfohlen anstatt Destroy die Funktion Free zu verwenden, weil diese auch für Referenzen, die nil sind, aufgerufen werden kann ohne, daß es zu einer Exception kommt. Das ist soweit richtig und würde ich auch dir empfehlen. (Bzw. ich komme gleich noch auf etwas empfehlenswerteres.) Leider steht dabei nichts darüber was mit der Referenz nach dem Destroy, bzw. Free geschieht. Ich vermute mal, daß sie nach wie vor auf das soeben freigegebene Objekt zeigt. Somit liefert Assigned() nach wie vor ein True zurück. Es ist sogar möglich weiterhin fehlerfrei über die Objektreferenz auf das zerstörte Objekt zu zugreifen, nämlich solange der Speicher nicht verändert wurde. Da aber der Speicher freigeben wurde, kann niemand voraussagen wie lange das gut geht.<p>
            Weiter kann man unter TObject.Free auch lesen: (Ich zitiere)<p>
            Im Gegensatz zu Destroy funktioniert Free auch dann, wenn das Objekt nil ist. Es ist also kein Fehler, die Methode für ein Objekt aufzurufen, das niemals initialisiert wurde.<p>
            Zitatende.<p>
            Der erste Satz ist richtig. Der zweite schlicht weg falsch. Wie Hagen oben erwähnt hat, ist die Referenz noch nicht initialisiert und folgender Code führt zu einer Zugriffsverletzung:<pre>
            procedure TForm1.FormCreate(Sender: TObject);
            var
            Objekt: TObjectList;
            begin
            Objekt.Free;
            ...
            end;</pre>
            Daraus folgt, daß eine Objektreferenz so früh als möglich durch einen Konstruktoraufruf oder, wenn sie erst später verwendet werden soll, durch eine nil-Zuweisung initialisiert werden sollte.<br>
            Nachdem Zertören eines Objektes via Free sollte die Objektreferenz anschließend sofort auf nil gesetzt werden. Das geht auch in einem Aufwasch, nämlich mittels der Prozedur FreeAndNil aus der Unit Sysutils. Geht man konsequenterweise so vor, so liefert Assigned stets ein korrektes Ergebnis. Leider steht das nicht so in der Delphi-Hilfe, zumindest nicht an den Stellen an denen ich es erwarten würde, nämlich gerade bei Destroy und Free. (Gilt zumindest bis Delphi 5, vielleicht wurde die Hilfe bei 6 oder 7 ja inzwischen verbessert.)<p>
            Gruß Wolfgang Rolle

            Comment


            • #7
              Hallo Marcus,

              Ich habe mir Deinen Beitrag noch einmal genauer angesehen, und glaube, dass wir mit unserer Beiträgen an Deinem eigentlichen Problem vorbeidiskutiert haben.

              Warum !? - Nun Du beschreibst, das Du die Variable Index(wahrscheinlich TListView.Selected.Index) auf Nil überprüftst. Das macht jedoch keinen Sinn, da die Variable eine vom Typ Integer ist und dieselbe eigentlich nicht den Wert NIL annehmen kann.

              Folgendes Beispiel jedoch könnte Deine Rettung sein.

              <PRE> If ListView1.Selected = nil then exit else</PRE>
              <PRE> ListView1.Selected.Caption:='';</PRE>
              <PRE> ListView1.Selected.ImageIndex:=0;</PRE>
              <PRE> ...</PRE>

              Ich hoffe ich konnte Dir damit ein wenig helfen !? Aber eines musst Du mir noch erklären; warum soll die Möglichkeit mit if..then nicht funktionieren !?

              Gruß, To

              Comment


              • #8
                @Tom, <I>Bitte nimm es mir nicht übel, aber dieser Beitrag wurde im Kapitel Delphi-Neulinge eröffnet. Aus diesem Grund habe ich behauptet, das man die Funktion Assigned mit Vorsicht genießen sollte.</i>

                Da sind wir uns doch einig, nur habe ich Deine auf "Assigned" bezogene Aussage erweitert und das eigentliche Problem generalisiert. Dieses besteht eben darin das Assined() nur das korrekt überprüfen kann was durch den Programmierer korrekt gehandhabt wurde. D.h. in meinen obigen Beispielen wird nur gezeigt das das gleiche Problem sich hinter vielen verschiedenen Fehlern verbergen kann, und nicht nut hinter Assigned().

                Gruß Hage

                Comment


                • #9
                  Hallo Hagen,

                  Ich denke, dass ich Deinen Beitrag eher mißverstanden habe. Ein Grund dafür könnte sein, dass man in einem Forum die Tonlagen in einem Satz nicht erkennen kann.

                  Natürlich, stimme auch ich Deiner Meinung zu und hoffe, dass Du mir meinen etwas gehobenen Ton im darauf gefolgtem Beitrag nicht übel nimmst. Schleim !!

                  Gruß Tom

                  Comment


                  • #10
                    @Wolfgang, die Aussagen der Hilfe sind im Grunde korrekt. Es gibt dort zwei Zustände einer Object-Referenz. 1. "nil" = Integer(nil) = 0 und 2. <> nil -> Zeiger auf ein gültiges Object.<br>
                    D.h. der Compiler selber MUSS davon ausgehen das irgendwelche Daten immer korrekt initialisiert UND finalisiert werden. Dafür ist der Programmierer verantworlich. "Leider" wurde Delphi die letzten Jahre weiterentwickelt und so kamen viele "Auto"-Datentypen, wie LongStrings, Interfaced Objecte, Variants usw. hinzu. All diese neueren Datentypen unterstützen die autom. Initialisierung, Refenrenzzählung und Finalisierung.<br> In deren Fall würde eine "Assigned" immer korrekt arbeiten.<br>
                    Im Fall der "veralteten" manuellen Datentypen muß man halt immer selber darauf achten das sie gültig sind.<br>
                    Mit Delphi.NET könnte sich das vielleicht erledigt haben.<br>

                    @Thomas van Veen: kann passieren.<br>

                    Gruß Hage

                    Comment


                    • #11
                      Zuerst einmal vielen Dank an alle. Leider konnte ich den Verlauf der Diskussion nicht mitverfolgen, da ich Beruflich verhindert war (sorry).

                      Ich denke Thomas van Veen hat mir dabei am meisten weitergeholfen. Das prob ist, das ich beim Abfragen von selected.index eine exception bekam, wenn ich ins leere Klicke.
                      Um dies zu umgehen, versuchte ich es mit

                      if ListView1.Selected.index = nil then exit;

                      was nicht funktionierte. :-((

                      Einfach .index weglassen und schon funktioniert es. :-)))

                      Na ja, man lernt nie aus

                      Comment

                      Working...
                      X