Почему варианты Delphi не могут содержать объекты? - PullRequest
14 голосов
/ 14 декабря 2008

Почему варианты Delphi не могут содержать объекты? Что еще более важно, в чем причина этого ограничения?

Ответы [ 3 ]

25 голосов
/ 14 декабря 2008

Вы можете определенно сохранить объект внутри переменной Variant - просто приведите его в NativeUInt. В любом случае, объект - это просто указатель.

obj := TObject.Create;
v := NativeUInt(obj);
obj := TSomeObject(NativeUInt(v));
8 голосов
/ 14 декабря 2008

Это просто мнение, исходя из моего опыта, что варианты могут и не могут делать.

Если вы поместите в него COM-объект, он будет сохранен как ссылка IDispatch, и, таким образом, любые вызовы методов или свойства, к которым вы обращаетесь к этому объекту, будут преобразованы в некоторый код, который ищет внутренний DISPID метода / свойства будет создан массив с аргументами метода, и метод будет вызван через интерфейс IDispatch.

Другими словами, IDispatch обрабатывается для вас так, как вы обычно это делаете, но компилятор делает это автоматически.

Однако для обычных объектов Delphi все становится сложнее. Вы можете использовать RTTI для поиска и вызова опубликованных методов и свойств, но это все. Если у вас есть имя неопубликованного, не виртуального метода, Delphi не может найти правильный адрес для него в вашем методе.

Другими словами, все, что вы могли бы сделать, это просто удерживать объект, вы не сможете его использовать. Возможно, они могли бы добавить поддержку только для его освобождения, но, опять же, это могло бы быть так.

Я точно знаю, что если вы правильно внедрили IDispatch, вы можете безопасно хранить и использовать объект через один из вариантов. У меня есть класс, который можно использовать в качестве базового класса для объектов Delphi, с которыми вы хотите это сделать. Он автоматически выставляет опубликованные методы / свойства, и вы можете добавить больше, если хотите, с помощью некоторых вызовов защищенных методов. Если есть интерес к такому классу, я могу разместить его где-нибудь.

Но, опять же, это через IDispatch, и он использует опубликованные методы, остальное - ручной код, поэтому поддержка вариантов должна быть встроена в ваши объекты, вами.

Именно поэтому я думаю, что они просто сказали: это просто вызовет жалобы, что мы можем держать предмет, но это просто бесполезно.

Но это только мои мысли. Возможно, у кого-то из чиновников гораздо лучший ответ.

7 голосов
/ 14 декабря 2008

Я использовал Variants для хранения объектов в прошлом, используя внутренние компоненты Variant, код выглядит примерно так:

var
  MyObject: TMyObject;
  Value: Variant;
begin
  MyObject:= TMyObject.Create;
  TVarData(Value).VType:= VarByRef or VarUnknown;
  TVarData(Value).VPointer:= MyObject;
...