Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Неинициализированная переменная


Автор: shmelina 27.1.2010, 02:32
Часто бывает нужно, для самоконтроля, чтобы если забыл инициализировать переменную, то при попытке использования этой переменной, программа тебе ошибку выдаст.

Например, есть переменная типа Integer. По своему алгоритму я ее должен инициализировать (установить какое-то значение). Но могу ведь и забыть. А там ведь число уже какое-то есть. Было бы здорово, если бы там Null был. Ну или что-то подобное. Было так же хорошо, чтобы я мог сбросить установленное ранее значение, чтобы переменная снова стала неинициализированной (как бы Null установить).

Сейчас я использую для этих целей типом Variant. Но он больно тяжеловат. Да и туда кроме Integer можно и сроку и указатель запихнуть. А хотелось бы только (в данном случае) Integer или Null.

Другой пример: Моя программа активно общается с базой данных. Мне нужно считать значение внешнего ключа и запихнуть в переменную. Но внешний ключ не Not Null и там спокойно может быть Null.

Только тип Variant? Может какой тип данных для этого есть, а я его не знаю?

Автор: Alexeis 27.1.2010, 10:47
Цитата(shmelina @  27.1.2010,  01:32 Найти цитируемый пост)
Часто бывает нужно, для самоконтроля, чтобы если забыл инициализировать переменную, то при попытке использования этой переменной, программа тебе ошибку выдаст.

  Делфи это объектно ориентированный язык. Все самое вкусное через объекты. Любой объект при создании зануляет все свое содержимое в том числе и записи и строки и массивы указатели, не говоря уже про простые числа.
  Создал объект можешь забыть про зануление его полей. Другое дело нуль не всегда правильная инициализация. В этом случае нужно в конструкторе объекта присваивать начальные значения (если они должны быть отличными от нуля).

Автор: Frees 27.1.2010, 11:10
Цитата(shmelina @  27.1.2010,  05:32 Найти цитируемый пост)
Например, есть переменная типа Integer. По своему алгоритму я ее должен инициализировать (установить какое-то значение). Но могу ведь и забыть. А там ведь число уже какое-то есть. Было бы здорово, если бы там Null был.

NULL может быть только у variant

Автор: CodeMonkey 27.1.2010, 12:27
Ну, напрямую такое не поддерживается, но можно делать хаками.

http://forum.sources.ru/index.php?showtopic=293134&view=findpost&p=2485530. http://blogs.embarcadero.com/abauer/2008/09/18/38869.

Добавлено через 58 секунд
http://cc.embarcadero.com/Item/26916.

Автор: Dom 27.1.2010, 14:05
Напомню, что у числовых значений может быть значение NAN (not a number).
Возможно это будет полезным в вашем случае. Только с ним аккуратно работать надо, а то могут быть грабли.

Автор: RomanEEP 28.1.2010, 12:16
NAN - только у чисел с плавающей точкой, у Integer его нет

Автор: shmelina 28.1.2010, 20:27
Цитата(Alexeis @  27.1.2010,  10:47 Найти цитируемый пост)
Делфи это объектно ориентированный язык. Все самое вкусное через объекты. Любой объект при создании зануляет все свое содержимое в том числе и записи и строки и массивы указатели, не говоря уже про простые числа.
  Создал объект можешь забыть про зануление его полей. Другое дело нуль не всегда правильная инициализация. В этом случае нужно в конструкторе объекта присваивать начальные значения (если они должны быть отличными от нуля).

Это я все понимаю. Но 0 в типе Integer, это уже наличие значения. А мне нужно как в объектах - или есть значение или нет его (nil). Если значения нет и пытаешься сделать Form.Close, то выдается ошибка. Я так же и простым типом Integer хочу.

Цитата(Frees @  27.1.2010,  11:10 Найти цитируемый пост)
NULL может быть только у variant 

:(

Цитата(CodeMonkey @  27.1.2010,  12:27 Найти цитируемый пост)
Ну, напрямую такое не поддерживается, но можно делать хаками.
Например. Или так.
Добавлено через 58 секунд
А вот ещё. 

Идею понял. Но не понял как обнулять (сбрасывать) значение. Еще вопрос, что более быстро работает эта идея с дженериками (Nullable<Integer>) или тупо Variant? Плохо, что это не родной для Delphi тип и имеются некоторые ограничения при использовании по сравнению с Integer.

Цитата(Dom @  27.1.2010,  14:05 Найти цитируемый пост)
Напомню, что у числовых значений может быть значение NAN (not a number).
Возможно это будет полезным в вашем случае. Только с ним аккуратно работать надо, а то могут быть грабли. 

Спасибо. Не знал. Но он ошибок не выдает при использовании. А в результате вычисления с неинициализированной переменной видим NAN. Где ошибка была - не понятно.

Цитата(RomanEEP @  28.1.2010,  12:16 Найти цитируемый пост)
NAN - только у чисел с плавающей точкой, у Integer его нет 

Угу.

Жаль нет NullableInteger.

Использовать Variant и не парится?

Автор: Frees 28.1.2010, 20:56
Цитата(shmelina @  28.1.2010,  23:27 Найти цитируемый пост)
Использовать Variant и не парится?

будешь парится в другом месте

например:


это исключение
Код

var v: variant; i : integer;

v := NULL;
i := v;



а это нет
Код

var v: variant; i : integer;

v := 0;
i := v;

Автор: shmelina 28.1.2010, 22:02
Цитата(Frees @  28.1.2010,  20:56 Найти цитируемый пост)
например

Ты что мне хотел этими примерами показать? Это, конечно же, я понимаю.

Автор: Frees 28.1.2010, 22:19
Цитата(shmelina @  29.1.2010,  01:02 Найти цитируемый пост)
Ты что мне хотел этими примерами показать


если хочеш интеджер поменять на вариант то это шило на мыло(одни грабли на другие)

Автор: CodeMonkey 29.1.2010, 11:45
Цитата(shmelina @  28.1.2010,  20:27 Найти цитируемый пост)
Но не понял как обнулять (сбрасывать) значение.

Смотря какой способ. В общем случае это надо сделать доп. метод.

Пример с adv. records:

Код
type
  ENullError = class(Exception);

  NullableInteger = record
  private
    FNotNull: String;
    FValue: Integer;
    function GetIsNull: Boolean;
    function GetValue: Integer;
    procedure SetValue(const AValue: Integer);
  public
    property Value: Integer read GetValue write SetValue;
    property IsNull: Boolean read GetIsNull;
    procedure Clear;
    class operator Implicit(const AValue: Integer): NullableInteger;
    class operator Explicit(const AValue: Integer): NullableInteger;
    class operator Implicit(const AValue: NullableInteger): Integer;
    class operator Explicit(const AValue: NullableInteger): Integer;
  end;

resourcestring
  rsNullValue = 'Value is NULL';

{ NullableInteger }

procedure NullableInteger.Clear;
begin
  FNotNull := '';
end;

function NullableInteger.GetIsNull: Boolean;
begin
  Result := (FNotNull = '');
end;

function NullableInteger.GetValue: Integer;
begin
  if IsNull then
    raise ENullError.Create(rsNullValue);
  Result := FValue;
end;

procedure NullableInteger.SetValue(const AValue: Integer);
begin
  FNotNull := '1';
  FValue := AValue;
end;

class operator NullableInteger.Implicit(const AValue: Integer): NullableInteger;
begin
  Result.Value := AValue;
end;

class operator NullableInteger.Implicit(const AValue: NullableInteger): Integer;
begin
  Result := AValue.Value;
end;

class operator NullableInteger.Explicit(const AValue: Integer): NullableInteger;
begin
  Result.Value := AValue;
end;

class operator NullableInteger.Explicit(const AValue: NullableInteger): Integer;
begin
  Result := AValue.Value;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I: NullableInteger;
begin
  Caption := BoolToStr(I.IsNull, True);

  I := 5;
  Caption := Caption + ' ' + IntToStr(I);

  I.Clear;
  Caption := Caption + ' ' + IntToStr(I);
end;


По аналогии и с генериками.

Автор: sCreator 29.1.2010, 12:11
А использование ссылки на integer не подойдет ?
Код

i = ^Integer;

не инициализированная ссылка имее значение nil ( только надо остарожно с локальными переменными ) 
и i^ если i = nil должно дать исключение
Но придется возиться с динамическим выделением памяти - зато остальное быстро.

Автор: shmelina 29.1.2010, 14:09
В общем буду вариантом пользоваться. Все остальное сложно.
Всем спасибо за помощь в этом вопросе. Узнал кое-что новое.

Автор: Frees 29.1.2010, 14:12
Цитата(shmelina @  29.1.2010,  17:09 Найти цитируемый пост)
В общем буду вариантом пользоваться. 

про VarisNULL и VarIsEmpty не забывай )))

Автор: shmelina 29.1.2010, 16:38
Цитата(Frees @  29.1.2010,  14:12 Найти цитируемый пост)
про VarisNULL и VarIsEmpty не забывай ))) 

Я обычно сразу Null присваиваю.

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