14.1.1 内联变量和泛型类型推断
在声明泛型变量时,声明可能相当长。在创建该类型的对象时,必须重复相同的声明。除非您利用内联变量声明及其变量类型推断的能力。因此,上面最后一个代码片段可以写成:
begin
var Kvi := TKeyValue<Integer>.Create;
try
// ...
finally
Kvi.Free;
end;
在这个代码中,你不必两次重复完整的泛型类型声明。这在使用容器时特别方便,我们将在后面看到。
14.1.2 泛型类型的规则
当你声明一个泛型类型的实例时,该类型会得到一个具体的版本,编译器会在所有后续操作中使用该版本。因此,如果你有一个泛型类,比如:
type
TSimpleGeneric<T> = class
Value: T;
end;
当你声明一个具体类型的对象时,你不能为 Value 字段指定不同的类型。鉴于以下两个对象,下面的一些赋值(TypeCompRules 示例的一部分)是不正确的:
var
Sg1: TSimpleGeneric<string>;
Sg2: TSimpleGeneric<Integer>;
begin
Sg1 := TSimpleGeneric<string>.Create;
Sg2 := TSimpleGeneric<Integer>.Create;
Sg1.Value := 'Foo';
Sg1.Value := 10; // 错误
// E2010 不兼容的类型:“string”和“Integer”
Sg2.Value := 'Foo'; // 错误
// E2010 不兼容的类型:“Integer”和“string”
Sg2.Value := 10;
end;
一旦在泛型声明中定义了具体类型,编译器将强制执行对具体类型的检查,这符合Object Pascal等强类型语言的预期。对于泛型对象作为整体,也适用类型检查。当为对象指定泛型参数时,不能将一个不同且不兼容类型的相似泛型类型分配给它。如果这看起来令人困惑,下面的示例应该有助于澄清这个情况:
Sg1 := TSimpleGeneric<Integer>.Create; // 错误
// E2010 不兼容的类型:
// 'TSimpleGeneric<System.string>'
// 和 'TSimpleGeneric<System.Integer>'
正如我们将在 "通用类型兼容性规则 "一节中看到的,在这种特殊情况下,类型兼容性规则是按结构而不是按类型名制定的。一旦声明了泛型类型,就不能再为其分配不同的、不兼容的类型。