我想声明一个这样的类型:
type
TDynMatrix<T> = TArray<TArray<T>>;
编译器拒绝这一点:
[dcc32 Error] E2508 Type parameters not allowed on this type
我想知道这个问题是否与泛型的嵌套有关。但似乎不是:
type
TDynArray<T> = TArray<T>;//pointless type I know, but for the sake of the Q
也会导致相同的编译错误。
编译器错误的documentation让我知道在读之前可能比我知道的还要少:
此类型不允许使用E2508类型参数(Delphi)
使用类引用时,不能直接使用泛型类。 您需要使用包装类才能使用泛型。
program E2508; {$APPTYPE CONSOLE} uses SysUtils; type TMyClass = class end; TMyClassClass<T> = class of TMyClass; begin Writeln('FAIL - E2508 type parameters not allowed on this type'); end.
有谁可以解释为什么我不能用这种方式声明泛型类型?
答案 0 :(得分:3)
抱歉没有理由,但这个不仅限于TArray,
使用以下类型定义:
TGenClass<T> = class fx: T; end;
TGenArray<T> = array of T;
TGenRecord<T> = record fx: T; end;
TGenProc<T> = procedure(const A: T);
我尝试了所有组合:
TGenClassClass<T> = TGenClass<TGenClass<T>>;
TGenClassArray<T> = TGenClass<TGenArray<T>>;
TGenClassRecord<T> = TGenClass<TGenClass<T>>;
TGenClassProc<T> = TGenClass<TGenClass<T>>;
TGenArrayClass<T> = TGenArray<TGenClass<T>>;
TGenArrayArray<T> = TGenArray<TGenArray<T>>;
TGenArrayRecord<T> = TGenArray<TGenClass<T>>;
TGenArrayProc<T> = TGenArray<TGenClass<T>>;
TGenRecordClass<T> = TGenRecord<TGenClass<T>>;
TGenRecordArray<T> = TGenRecord<TGenArray<T>>;
TGenRecordRecord<T> = TGenRecord<TGenClass<T>>;
TGenRecordProc<T> = TGenRecord<TGenClass<T>>;
TGenProcClass<T> = TGenProc<TGenClass<T>>;
TGenProcArray<T> = TGenProc<TGenArray<T>>;
TGenProcRecord<T> = TGenProc<TGenClass<T>>;
TGenProcProc<T> = TGenClass<TGenProc<T>>;
他们都失败了。
如果这些类型不是通用的,您可以声明具有复杂类型表达式的类型:
TClassClass = TGenClass<TGenClass<Integer>>;
TClassArray = TGenClass<TGenArray<Integer>>;
TClassRecord = TGenClass<TGenClass<Integer>>;
TClassProc = TGenClass<TGenClass<Integer>>;
TArrayClass = TGenArray<TGenClass<Integer>>;
TArrayArray = TGenArray<TGenArray<Integer>>;
TArrayRecord = TGenArray<TGenClass<Integer>>;
TArrayProc = TGenArray<TGenClass<Integer>>;
TRecordClass = TGenRecord<TGenClass<Integer>>;
TRecordArray = TGenRecord<TGenArray<Integer>>;
TRecordRecord = TGenRecord<TGenClass<Integer>>;
TRecordProc = TGenRecord<TGenClass<Integer>>;
TProcClass = TGenProc<TGenClass<Integer>>;
TProcArray = TGenProc<TGenArray<Integer>>;
TProcRecord = TGenProc<TGenClass<Integer>>;
TProcProc = TGenClass<TGenProc<Integer>>;
有规避。您可以使用类型参数在类中声明类型。
type
TTheClass<T> = class
type
TGenClassClass = TGenClass<TGenClass<T>>;
end;
因此,您可以使用TTheClass<T>.TGenClassClass
作为类型。
答案 1 :(得分:3)
您的代码无效,因为您无法将泛型类型重新声明为开放泛型类型。
我会将其声明为:
type
TDynMatrix<T> = array of TArray<T>;
通过这种方式,您仍然可以使用兼容性:一维到TArray<T>
的元素。
那么你可以写
var
matrix: TDynMatrix<Integer>;
values: TArray<Integer>;
....
SetLength(matrix, 2, 2);
values := matrix[0];
values := Copy(matrix[1]);
等。
答案 2 :(得分:1)
FWIW受各种评论和答案的启发,这是我认为最有效的代码:
type
TDynMatrix<T> = array of TArray<T>;
TDynMatrix = class
public
class function New<T>(const Source: array of TArray<T>): TDynMatrix<T>; static;
end;
class function TDynMatrix.New<T>(const Source: array of TArray<T>): TDynMatrix<T>;
var
i: Integer;
begin
SetLength(Result, Length(Source));
for i := 0 to high(Result) do begin
Result[i] := Copy(Source[i]);
end;
end;
这允许声明这样的变量:
var
RealM: TDynMatrix<Real>;
ComplexM: TDynMatrix<TComplex>;
并制作这样的新实例:
RealM := TDynMatrix.New<Real>([TArray<Real>.Create(...)]);
ComplexM := TDynMatrix.New<TComplex>([TArray<TComplex>.Create(...)]);
现在,如果只有编译器的通用推理功能更好一点。