E1012错误:使用in操作符匹配3个常量触发子范围越界,如何解决?
Delphi编译错误E1012的解决方法(保留
in操作符) 问题描述
编译代码时触发错误E1012:Constant expression violates subrange bounds,出错代码如下:
procedure test(); const one = 100; two = 200; three = 300; var arr: TArray<smallint>; begin SetLength(arr, 1); arr[0] := 100; if arr[0] in [one, two] then Exit(); if arr[0] in [one, two, three] then Exit(); // 此行触发编译错误 end;
第一个条件语句正常,第二个却报错,希望继续使用in操作符完成这类值匹配判断。
原因分析
Delphi对in操作符的集合有严格限制:集合的基类型必须是子范围元素总数不超过256的类型(比如Byte、枚举类型等)。当你用smallint类型变量和常量集合比较时,编译器会默认将集合解析为set of 0..255(这是smallint的一个合法子范围,且元素数量符合集合限制)。第一个条件里的100、200都在0..255范围内,所以编译通过;但第二个条件里的300超出了这个子范围的上限,直接触发编译错误。
解决方法
以下几种方案可以让你继续使用in操作符,或者实现等价的判断逻辑:
1. 显式声明匹配目标范围的子类型
定义一个覆盖所有目标常量的子类型,用该类型的集合进行判断:
procedure test(); type TValidValueRange = 0..300; // 范围覆盖所有常量值 const one = 100; two = 200; three = 300; var arr: TArray<smallint>; currentVal: TValidValueRange; begin SetLength(arr, 1); arr[0] := 100; // 先转换为子类型(确保值在范围内,若有超出风险需先做检查) currentVal := TValidValueRange(arr[0]); if currentVal in [one, two] then Exit(); if currentVal in [one, two, three] then Exit(); // 正常编译 end;
如果arr[0]的值可能超出TValidValueRange的范围,建议先加范围判断,避免类型转换抛出异常。
2. 基于枚举类型实现集合判断(适合固定业务值)
如果这些常量是固定的业务标识,可以用枚举类型+映射表的方式:
procedure test(); type TTargetValue = (tvOne, tvTwo, tvThree); const one = 100; two = 200; three = 300; // 枚举值到实际数值的映射 ValueMap: array[TTargetValue] of smallint = (one, two, three); var arr: TArray<smallint>; valEnum: TTargetValue; begin SetLength(arr, 1); arr[0] := 100; // 先找到数值对应的枚举值,再用in判断 for valEnum := Low(TTargetValue) to High(TTargetValue) do begin if arr[0] = ValueMap[valEnum] then begin if valEnum in [tvOne, tvTwo] then Exit(); if valEnum in [tvOne, tvTwo, tvThree] then Exit(); Break; end; end; end;
3. 用辅助函数模拟in逻辑(无需类型转换)
如果不想改动类型定义,写一个辅助函数实现等价的判断:
// 判断smallint值是否在目标列表中 function IsInSmallIntList(const CheckValue: smallint; const TargetValues: array of smallint): Boolean; var i: Integer; begin Result := False; for i := Low(TargetValues) to High(TargetValues) do begin if CheckValue = TargetValues[i] then begin Result := True; Break; end; end; end; procedure test(); const one = 100; two = 200; three = 300; var arr: TArray<smallint>; begin SetLength(arr, 1); arr[0] := 100; if IsInSmallIntList(arr[0], [one, two]) then Exit(); if IsInSmallIntList(arr[0], [one, two, three]) then Exit(); // 正常编译 end;
内容的提问来源于stack exchange,提问作者user21732817
相关产品推荐
相关产品推荐

