powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Узнать наследника TList<>
27 сообщений из 27, показаны все 2 страниц
Узнать наследника TList<>
    #39646264
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно ли как-то узнать, что переданный объект является экземпляром класса или наследником TList<T>?

Если указать конкретный тип
Код: pascal
1.
2.
Obj := TList<Integer>.Create;
if Obj is TList<Integer> then

то все определяет. А мне бы узнать для произвольного типа
Код: pascal
1.
if Obj is TList<> then

Задача решается?


С уважением, Vasilisk
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646275
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Тут есть одна проблема, которая заключается в том что класса TList<T>, как такового, не существует. Существуют классы TList<Integer>, TList<Byte> и т.п., которые создаются при их первом использовании. Т.е. в операторе is экземпляр не с чем сравнивать.

Как вариант вижу такое извращение:
Код: pascal
1.
if Pos('TLIST<', AnsiUpperCase(List.ClassName)) = 1 then


Но тут могут быть нюансы: например, если в проекте есть несколько TList<>, объявленные в разных модулях - таким образом не получится отличать их друг от друга.
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646277
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А для наследника там вообще опа.
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646279
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

Этот вариант я рассматривал. Все решается. И разные классы и наследники. Не хотелось со строками связываться
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646292
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Код: pascal
1.
2.
3.
4.
    List := TList<Integer>.Create;
    WriteLn(List.ClassName);
    WriteLn(List.ClassParent.ClassName);
    WriteLn(List.ClassParent.ClassParent.ClassName);

Код: plaintext
1.
2.
TList<System.Integer>
TEnumerable<System.Integer>
TObject
Не вижу других вариантов...
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646297
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpНе вижу других вариантов...Вот так и сделал
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
function IsList(AObject: TObject): Boolean;
var
  LClass: TClass;
  LName: String;
  LPos: Integer;
begin
  LClass := AObject.ClassType;
  while LClass <> nil do begin
    if LClass.UnitName = TList<Byte>.UnitName then begin
      LName := LClass.ClassName;
      LPos := Pos('<', LName);
      if
        (LPos > 0) and
        (Pos('>', LName) = Length(LName)) and
        LName.StartsWith('TList')
      then begin
        Exit(True);
      end;
    end;
    LClass := LClass.ClassParent;
  end;
  Result := False;
end;
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646300
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Даже вот так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
function TJsonParser.IsList(AObject: TObject): Boolean;
var
  LClass: TClass;
  LName: string;
begin
  LClass := AObject.ClassType;
  while LClass <> nil do begin
    if LClass.UnitName = TList<Byte>.UnitName then begin
      LName := LClass.ClassName;
      if (Pos('>', LName) = Length(LName)) and LName.StartsWith('TList<') then
        Exit(True);
    end;
    LClass := LClass.ClassParent;
  end;
  Result := False;
end;



Вот это условие
Код: pascal
1.
Pos('>', LName) = Length(LName)

позволяет отбросить вложенные типы
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646302
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

А почему недостаточно этого?
Код: pascal
1.
LName.StartsWith('TList<')
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646307
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpА почему недостаточно этого?
Код: pascal
1.
LName.StartsWith('TList<')

Я же написал - можно нарваться на вложенные типы
Код: pascal
1.
TList<System.string>.TEnumerator
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646357
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Тогда уж заменить условие на:
Код: pascal
1.
if LName.StartsWith('TList<') and (LName[Length(LName)] = '>') then ...

это будет быстрее чем Pos().

Хотя мой вариант обломается на вложенном дженерике, а исходный - на чём-то вроде такого:
Код: pascal
1.
TList<TList<Integer>>

:)
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646375
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpэто будет быстрее чем Pos().Можно обломаться на
Код: pascal
1.
TList<System.string>.TInnerType<System.Integer>

(да, сейчас такого нет, но все же)
alekcvp
Код: pascal
1.
TList<TList<Integer>>

Ценное замечание. Спасибо. Будем думать
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646384
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpТогда уж заменить условие на:
Код: pascal
1.
if LName.StartsWith('TList<') and (LName[Length(LName)] = '>') then ...


это будет быстрее чем Pos().А если поменять операнды местами - то будет ещё быстрее :)
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646392
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_niggerэто будет быстрее чем Pos().А если поменять операнды местами - то будет ещё быстрее :)[/quot]
Ну да, я исходил из того чтобы не обломаться на пустой строке, а тут она не может быть пустой...
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646420
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
type
  Some = class helper for TObject
  public
    class function IsListOf<t>(): Boolean;
  end;

class function Some.IsListOf<t>(): Boolean;
begin
  Result := Self.InheritsFrom(TList<t>);
end;


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
type
  TL = class(TList<Integer>);

procedure Test();
var
  d: TL;
begin
  d := TL.Create;
  try
    Writeln('<Integer>:', d.IsListOf<Integer>());
    Writeln('<Byte>:', d.IsListOf<Byte>());
  finally
    d.Free;
  end;
end;

...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646525
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

хорошо :)
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646541
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

В т.з. стояла задача определить что класс - наследник TList<T> при неизвестном T.
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646545
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

хе ..., под вечер работать нельзя
наверное только строками, компилятор даже не связанные ни с чем методы выделить в один не может

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
type
  TL = class(TList<Integer>)
  private
    class function ErrorOffset(): Integer;
  end;
  Some = class helper for TObject
  private
    class function GetVMTProc(VMTProcIndex: Integer): Pointer;
  public
    class function IsList(): Boolean;
  end;

class function TL.ErrorOffset: Integer;
begin
  asm
    mov Result, vmtOffset Error
  end;
  Result := Result div SizeOf(Pointer);
end;

class function Some.GetVMTProc(VMTProcIndex: Integer): Pointer;
var
  p: pointer;
  VirtualMethodCount: word;
  m: PPointer;
begin
  p := PPointer(PByte(Self) + vmtMethodTable)^;
  VirtualMethodCount:= PWord(p)^;

  if VirtualMethodCount >= VMTProcIndex  then
    Exit(nil);

  m := Pointer(Self);
  inc(m, VMTProcIndex);
  Result := m^;
end;

class function Some.IsList(): Boolean;
type
  TP = procedure (const Msg: string; Data: NativeInt) of Object;
var
  v: TP;
  i: Integer;
  m: Pointer;
  c: TClass;
begin
  v := TL.Error;
  i := TL.ErrorOffset;
  c := Self;
  repeat
    m := c.GetVMTProc(i);
    if (m = nil) then
      Break;

    if TMethod(v).Code = m then
      Exit(True);
    c := c.ClassParent;
  until c = nil;
  Result := False;
end;


Код: pascal
1.
2.
3.
4.
5.
6.
procedure Test();
begin
  Writeln(TL.IsList);
  Writeln(TList<Byte>.IsList);
  Writeln(TList<Integer>.IsList);
end;



Код: plaintext
1.
2.
TRUE
FALSE
TRUE
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646754
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
Код: pascal
1.
class function IsListOf<t>(): Boolean;

Так и я могу :)

Можно даже проще
Код: pascal
1.
if Obj is TList<Integer> then

ноalekcvpВ т.з. стояла задача определить что класс - наследник TList<T> при неизвестном T.
В общем было принято пожертвовать вариантом_Vasilisk_
Код: pascal
1.
TList<System.string>.TInnerType<System.Integer>

в виду отсутствия на сегодня у TList<> вложенных дженерик типов

И получилось так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
function IsList(AObject: TObject): Boolean;
var
  LClass: TClass;
  LUnit: string;
  LName: string;
begin
  LClass := AObject.ClassType;
  LUnit := TList<Byte>.UnitName;
  while LClass <> nil do begin
    LName := LClass.ClassName;
    if
      (LName[Lenght(LName)] = '>') and
      (LClass.UnitName = LUnit) and
      LName.StartsWith('TList<')
    then
      Exit(True);
    LClass := LClass.ClassParent;
  end;
  Result := False;
end;
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646771
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

а заем тебе это надо? просто для развития? или какая-то цель практическая есть?
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646773
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)а заем тебе это надо?Пишу свой велосипед по сериализации/десериализации. И хочу, чтобы TList<> сериализовался как массив
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646851
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На, может поможет:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
function TArrayEx<T>.ToString(Delimeter: string): string;
var
  i : Integer;
  n : integer;
  s : string;
begin
  Result:='';
  for i:=Low to High do begin
    if (Result<>'') then begin
      s:=Delimeter+TValue.From<T>(Items[i]).ToString;
    end else begin
      s:=TValue.From<T>(Items[i]).ToString;
    end;

    n:=Length(Result);
    SetLength(Result,n+length(s));
    Move(s[1],Result[n+1],Length(s)*SizeOf(Char));
  end;
end;
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646916
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatНа, может поможет:Чем? Сериализатор я уже написал. Понятно, что если использовать свои классы, то можно сделать все, что угодно. Интересовало решение на стандартных. И именно детектирование стандартного класса
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #39646920
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Чем? Кто тебя знает.

Например
Код: pascal
1.
TValue.From<T>(Items[i]).ToString;
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Узнать наследника TList<>
    #40022799
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
_Vasilisk_,

Тут есть одна проблема, которая заключается в том что класса TList<T>, как такового, не существует. Существуют классы TList<Integer>, TList<Byte> и т.п.
У нас дженерики, а не шаблоны. Код экземпляров TList<Integer> и TList<Byte> будет один и тот же. Так что, по сути, существует только TList<T>.
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #40022816
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Квейд
Код экземпляров TList<Integer> и TList<Byte> будет один и тот же. Так что, по сути, существует только TList<T>.

Это не так.
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #40022826
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey
Квейд
Код экземпляров TList<Integer> и TList<Byte> будет один и тот же. Так что, по сути, существует только TList<T>.

Это не так.
Да, был неправ
...
Рейтинг: 0 / 0
Узнать наследника TList<>
    #40022839
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_nigger,
если отключен "complete boolean evaluation" )
...
Рейтинг: 0 / 0
27 сообщений из 27, показаны все 2 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Узнать наследника TList<>
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]