TypeInfo(T)は正しい方法です。さらに、TTypeDataレコードのようなTypInfoユニットのすべてのものを使用して、汎用タイプの代わりに使用するタイプの特定のプロパティを特定することができます。 Tの代わりに使用される現在の型を決定するときは、ポインタのトリックを使用して変数の値を取得できます。
ここでは、列挙型を汎用として受け入れるサンプルコードを示します。それと列挙プロシージャ内のローカル型として宣言されてはならない(=(第一= 1)、第二、第三の
が
TEnumWontWorkような固定値なし)のみ通常列挙のために働くことに注意してください。このような場合、コンパイラは列挙型のTypeInfoを生成しません。使い方の
type
// Sample generic class that accepts any enumeration type as T
TEnumArr<T> = class
strict private
fArr: array of Byte;
fIdxType: TOrdType;
function IdxToInt(idx: T): Int64;
procedure Put(idx: T; Val: Byte);
function Get(idx: T): Byte;
public
constructor Create;
property Items[Index: T]: Byte read Get write Put; default;
end;
constructor TEnumArr<T>.Create;
var
pti: PTypeInfo;
ptd: PTypeData;
begin
pti := TypeInfo(T);
if pti = nil then
Error('no type info');
// Perform run-time type check
if pti^.Kind <> tkEnumeration then
Error('not an enum');
// Reach for TTypeData record that goes right after TTypeInfo record
// Note that SizeOf(pti.Name) won't work here
ptd := PTypeData(PByte(pti) + SizeOf(pti.Kind) + (Length(pti.Name)+1)*SizeOf(AnsiChar));
// Init internal array with the max value of enumeration
SetLength(fArr, ptd.MaxValue);
// Save ordinal type of the enum
fIdxType := ptd.OrdType;
end;
// Converts index given as enumeration item to integer.
// We can't just typecast here like Int64(idx) because of compiler restrictions so
// use pointer tricks. We also check for the ordinal type of idx as it may vary
// depending on compiler options and number of items in enumeration.
function TEnumArr<T>.IdxToInt(idx: T): Int64;
var
p: Pointer;
begin
p := @idx;
case fIdxType of
otSByte: Result := PShortInt(p)^;
otUByte: Result := PByte(p)^;
otSWord: Result := PSmallInt(p)^;
otUWord: Result := PWord(p)^;
otSLong: Result := PLongInt(p)^;
otULong: Result := PLongWord(p)^;
end;
end;
function TEnumArr<T>.Get(idx: T): Byte;
begin
Result := fArr[IdxToInt(idx)];
end;
procedure TEnumArr<T>.Put(idx: T; Val: Byte);
begin
fArr[IdxToInt(idx)] := Val;
end;
サンプル:取得)T
2の一般的な小道具とTのためのTypeInfoを取得
1):履歴書として
type
TEnum = (enOne, enTwo, enThree);
var
tst: TEnumArr<TEnum>;
begin
tst := TEnumArr<TEnum>.Create;
tst[enTwo] := $FF;
Log(tst[enTwo]);
、私はここ3つのトリックを使用しましたTの型データTの詳細小道具T
3)ポインタの魔法を使ってparameの値を得るT型として与えられている。
このヘルプが必要です。
+1ありがとう!それはまさに私が探していたものです!あなたが私の元のアイデアのファンではない場合でも) – jpfollenius