You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:25:33