3 Stimmen

Delphi: Übergabe von TObject in Array von Variants

Ich habe eine Prozedur, die einen Parameter vom Typ TObject erwartet, etwa so:

MyProcedure (const AValue : TObject);

Ich habe ein Array von Variant, die ich bin Schleife durch die Prozedur aufrufen, etwas wie dieses:

  for i:=0 to High(myArray) do
    MyProcedure (myArray[i]);

Der Compiler gibt eine Fehlermeldung aus: "Inkompatible Typen: TObject und Variant".

Was kann ich tun, um dies zu umgehen?

Weitere Informationen: Bis jetzt habe ich einfache Typen (Strings, Zahlen, Daten) in Variant-Arrays übergeben (die Arrays sind in der Regel eine Mischung aus verschiedenen Typen - ich bin schließlich übergeben sie als Parameter an eine Datenbank gespeicherte Prozedur). Jetzt muss ich auch (in bestimmten Fällen) ein TObject übergeben.

Was ist die am besten geeignete Datentyp/Struktur, um die Werte zu übergeben, die sowohl einfache Typen und Objekte enthalten kann? Ich schätze, ich könnte meinen eigenen TParam-Typ erstellen, der ein Feld für beide hat, aber ich bin mir der genauen Syntax nicht sicher. Hat jemand ein Beispiel dafür?

8voto

Steve Claridge Punkte 9852

Eine Variante kann keine Objekte enthalten, sondern nur primitive Typen wie Integer und String.

Ich würde vorschlagen, dass Sie Ihr Array so ändern, dass es den gewünschten Typ hat und nicht eine Variante. Wenn Sie nicht sicher sind, der Objekttyp, den Sie wollen dann erstellen Sie ein Array von TObject oder die niedrigste mögliche Basisklasse der Objekte, die Ihr Array enthalten wird.

3voto

Toon Krijthe Punkte 51819

Sie können keine einfachen Objekte in einer Variante speichern. Aber Sie können Schnittstellen speichern.

var
  v : Variant;
  i : IInterface;

begin
  v := i; // Works perfectly;
end.

Sehen Sie sich die Typen für die Variante an:

varEmpty    = $0000; { vt_empty        0 }
varNull     = $0001; { vt_null         1 }
varSmallint = $0002; { vt_i2           2 }
varInteger  = $0003; { vt_i4           3 }
varSingle   = $0004; { vt_r4           4 }
varDouble   = $0005; { vt_r8           5 }
varCurrency = $0006; { vt_cy           6 }
varDate     = $0007; { vt_date         7 }
varOleStr   = $0008; { vt_bstr         8 }
varDispatch = $0009; { vt_dispatch     9 }
varError    = $000A; { vt_error       10 }
varBoolean  = $000B; { vt_bool        11 }
varVariant  = $000C; { vt_variant     12 }
varUnknown  = $000D; { vt_unknown     13 }
//varDecimal  = $000E; { vt_decimal     14 } {UNSUPPORTED as of v6.x code base}
//varUndef0F  = $000F; { undefined      15 } {UNSUPPORTED per Microsoft}
varShortInt = $0010; { vt_i1          16 }
varByte     = $0011; { vt_ui1         17 }
varWord     = $0012; { vt_ui2         18 }
varLongWord = $0013; { vt_ui4         19 }
varInt64    = $0014; { vt_i8          20 }
varUInt64   = $0015; { vt_ui8         21 }

Wenn Sie wirklich wollen, können Sie TObject in Pointer to Integer umwandeln und das speichern. Aber ich bin nicht sicher, ob das ist, was Sie wirklich wollen.

1voto

Toby Allen Punkte 10652

Meine erste Reaktion ist zu fragen, warum Sie TObjects in einer Liste von Varianten speichern, aber angenommen, Sie haben einen guten Grund!

Wenn Sie es geschafft haben, Ihre TObject-Instanz in erster Linie in das Array zu platzieren, dann haben Sie wahrscheinlich den Zeiger auf das Tobject platziert. In diesem Fall müssen Sie die Variant/Integer als TObject typisieren, z.B.

for i:=0 to High(myArray) do
    MyProcedure (TObject(myArray[i]));

Dies sollte funktionieren, aber wie bei jedem Typecasting ist es an Ihnen, sicherzustellen, dass myArray[i] tatsächlich ein Zeiger auf eine TObject-Instanz ist oder schreckliche Dinge passieren könnten.

Sind Sie sicher, dass eine TListe nicht das tun würde, was Sie wollen? Eine Variante ist eigentlich dazu gedacht, grundlegende Typen wie String, Integer, Float, Boolean und nicht Objekte zu speichern.

0voto

Steve Claridge Punkte 9852

Ich glaube nicht, dass es eine gute Idee ist, eine TParam mit einer Variant-Variable eine TOBject-Variable zu erstellen. Etwas wie:

Tobject = record
  prim: Variant;
  obj: TObject;
end

Das würde funktionieren, aber es erscheint mir sehr unübersichtlich. Pascal ist keine dyanmisch typisierte Sprache und ich würde nicht versuchen, sie wie eine solche zu behandeln. Ich würde entweder vorschlagen:

Erstellen Sie eine weitere Funktion zur Behandlung von Variant, so dass neben der

MyProcedure (const AValue : TObject);

haben auch

MyProcedure (const AValue : Variant);

und verwalten Sie Ihre Daten getrennt voneinander. Oder erstellen Sie einen Datensatz, der Ihre Dateneingaben definiert, zum Beispiel anstelle von TParam von Variante und Objekt haben etwas wie:

TStoredProcParm = record
  name: String;
  bought: TDateTime;
end;

und so weiter. Vielleicht haben Sie so viele verschiedene Daten, dass die Variante/Objekt-Route die beste ist, aber es scheint wie ein bisschen ein Wartungs-Kopfschmerzen - wenn Ihr anderer Code ein Array von Variant übergeben wird, wie wissen Sie, welche Variante ist, die und wie man jede von ihnen in Ihrem Stored proc verwenden?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X