【发布时间】:2022-01-27 20:24:10
【问题描述】:
Delphi 不直接支持将整数类型转换为枚举的任何范围检查或超出范围的异常提升。见:How do I convert an integer to an enumerated type? 我试图通过对枚举子范围索引的数组进行自动范围检查来解决这个问题。在我的测试程序中,我故意使用了非连续枚举,它禁用 RTTI 并为没有命名枚举但可以通过 typecasting、Inc、Dec 等访问的有效子范围值提供测试。
程序按预期处理子范围 (2) 的非枚举元素,但不会为枚举数组生成超出范围的异常 - 但会为等效的整数索引数组生成。这有什么好的理由吗?我可以使用整数索引数组来解决问题,但枚举索引会更健壮一些。
type MyEnum = (zero,one,three=3);
var EnumCheck: array[MyEnum] of integer = (0,1,2,3);
var iEnum: integer;
var MyEnumVar: MyEnum;
var IntArray: array[0..3] of integer = (0,1,2,3);
procedure Test;
begin
{$R+}
MyEnumVar:= MyEnum (1); // One
iEnum := EnumCheck[MyEnumVar]; // OK - iEnum = 1
MyEnumVar:= MyEnum (2); // Out-of-bound
iEnum := EnumCheck[MyEnumVar]; // OK - iEnum = 2
MyEnumVar:= MyEnum (3); // Three
iEnum := EnumCheck[MyEnumVar]; // OK - iEnum = 3
MyEnumVar:= MyEnum (4); // Out-of-bound
iEnum := EnumCheck[MyEnumVar]; // no Exception; iEnum is set to random value
iEnum := 4;
iEnum := IntArray[iEnum]; // Exception thrown here
iEnum := IntArray[4]; // Compiler "subrange" error
end;
使用 Delphi 10.4 更新 2
编辑:我找到了我的工作。将校验数组定义为:
var iCheck: array[Ord(Low(MyEnum))..Ord(High(MyEnum))] of integer = (0,1,2,3);
并按预期抛出超出范围的异常。
【问题讨论】:
-
我错过了您没有在值 4 上获得异常的部分,因此我删除了我的答案,因为它没有解决您的问题。您可以发布您的解决方法作为答案。
-
@Dalija 我还是很好奇为什么使用枚举索引的数组不会抛出范围检查异常。即使枚举本身没有经过范围检查,我也会认为数组会是。
-
目前我没有答案。也许这是出于某种更深层原因的预期行为,也许它只是编译器中的一个错误。
标签: delphi casting enumeration range-checking