Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Перечислимый тип, (out of bound)


Автор: RinOSpro 15.7.2010, 11:41
Всем привет)

Возник вопрос по поводу перечислимых типов. Точнее преобразования Integer -> "Перечислимый тип".

И так, объявлен тип TLMsgType = (ltError = 0, ltWarning, ltInformation, ltDebug);

сохраняю его в БД преобразованием в Integer, Integer(LMsgType). При загрузке и БД. Там может отказаться любое число которое не входит в диапазон (а входящие данные нужно проверять).

Вопрос в том как наиболее эффективно проверять входит в это число в диапазон Перечислимого типа или нет? Типов много... поэтому собственно и вопрос...

Наиболее простой вариант я написал

Код

function isRangeInType(const AValue: TLMsgType): Boolean; overload;
begin
//  Result := not (AValue < Low(TLMsgType)) or (AValue > High(TLMsgType)); представьте, так не работает)) (всегда возвращает true) сам в шоке ну не суть) ниже работающая версия

  if (AValue < Low(TLMsgType)) or (AValue > High(TLMsgType)) then
    Result := False
  else
    Result := True;
end;

Автор: casinosoftguru 15.7.2010, 14:37
 smile 
Цитата

//  Result := not (AValue < Low(TLMsgType)) or (AValue > High(TLMsgType)); представьте, так не работает)) (всегда возвращает true) сам в шоке ну не суть) ниже работающая версия


может быть потому что надо так smile

Код

Result := not (AValue < Low(TLMsgType)) or not (AValue > High(TLMsgType));

Автор: Keeper89 15.7.2010, 16:52
Думаю логично будет проверять Integer после чтения из БД:
Код

function isRangeInType(const AValue: Integer): Boolean;
begin

  Result := AValue in [Integer(Low(TLMsgType))..Integer(High(TLMsgType))];
end;

или
Код

function isRangeInType(const AValue: Integer): Boolean;
begin

  Result := (AValue >= Integer((Low(TLMsgType))) and (AValue <= Integer((High(TLMsgType)));
end;

А в коде вызывать:
Код

if isRangeInType(a) then
  b := TLMsgType(a)
else
  //

Автор: RinOSpro 15.7.2010, 17:28
Цитата(casinosoftguru @  15.7.2010,  14:37 Найти цитируемый пост)
может быть потому что надо так код Pascal/Delphi1:Result := not (AValue < Low(TLMsgType)) or not (AValue > High(TLMsgType));


Логически оно такое же как и я написал, и так же возвращает true в любом случае... может глюк? (Delphi 7)

Цитата(Keeper89 @  15.7.2010,  16:52 Найти цитируемый пост)
Думаю логично будет проверять Integer после чтения из БД:

Цитата(RinOSpro @  15.7.2010,  11:41 Найти цитируемый пост)
Вопрос в том как наиболее эффективно проверять входит в это число в диапазон


если много типов то это становиться не удобным... см. ниже

Цитата(Keeper89 @  15.7.2010,  16:52 Найти цитируемый пост)
  Result := AValue in [Integer(Low(TLMsgType))..Integer(High(TLMsgType))];


А вот за эту конструкцию спасибо!

Только если скажем у нас много перечислений... то для каждой придется написать кучу overload функций

Код

function isRangeInType(const AValue: TLMsgType): Boolean; overload;
begin
  Result := AValue in [Low(AValue)..High(AValue)];
end;

function isRangeInType(const AValue: TEnum1): Boolean; overload;
begin
  Result := AValue in [Low(AValue)..High(AValue)];
end;

function isRangeInType(const AValue: TEnum2): Boolean; overload;
begin
  Result := AValue in [Low(AValue)..High(AValue)];
end;

function isRangeInType(const AValue: TEnumN): Boolean; overload;
begin
  Result := AValue in [Low(AValue)..High(AValue)];
end;


Есть ли какая нибудь универсальная range-check функция? Или идеи... как бы такую написать 

 smile 
Код

function isRangeInType(const AValue): Boolean;
begin
  .........
end;


Автор: Keeper89 15.7.2010, 21:36
Цитата(RinOSpro @  15.7.2010,  17:28 Найти цитируемый пост)
Только если скажем у нас много перечислений... то для каждой придется написать кучу overload функций

Да, думаю так и придется.

Автор: bems 18.7.2010, 23:19
Функция
Код

uses
  TypInfo;

 function IsValInRange(Value: Integer; EnumType: PTypeInfo): Boolean;
 var pData: PTypeData;
 begin
 Assert(EnumType.Kind = tkEnumeration);
 pData := GetTypeData(EnumType);
 Result := Value in [pData.MinValue..pData.MaxValue]
 end;

Вызов
Код

if not IsValInRange(1, TypeInfo(Boolean))
   then raise Exception.Create('Покоцаная база данных. Ищи бекап.');

Автор: Демо 19.7.2010, 11:14
Код

  TMyEnum=(meNone=10, meYes=1000, meNo=-1000);


Сдаётся мне, что самое простое - обрабатывать исключение.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)