Delphi - Как вы разрешаете конфликт, когда имя элемента совпадает с именем свойства?

Тривиальный пример ниже - это конденсация проблемы, с которой я пытался разрешить конфликт, когда у меня был элемент перечисленного типа с тем же именем, что и член VCL.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
    TSomeType = (
      alNone,
      alSome,
      alMany) ;

procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Align := alNone ;                    // 1.  type mismatch
Self.Align := Controls.alNone ;           // 2.  "Controls" is also a property of TForm
end ;

end.
  • Первое присваивание не выполняется, потому что компилятор считает, что alNone - это тот, который я объявил, а не элемент TAlign, определенный в Controls.pas.
  • Второе неудачно, потому что для TForm для этого имени требуется Controls.

Я понимаю, что есть способы обойти это (переименование элемента alNone является самым простым), но мне любопытно, есть ли способ присвоить ссылку на свойство в другом блоке, где имя элемента конфликтует с идентификатор в текущей области.

Ответ 1

Отметьте его именем типа:

TAlign.alNone

Я не понял, когда написал это, что актуальна версия компилятора. Этот синтаксис стал доступен только в Delphi 2010 или XE. Там ответ не подходит для помеченной версии, Delphi 2007. Deltics ответ охватывает гораздо более подробно.

Ответ 2

Как подсказывает Дэвид, для типа перечисления или другой ситуации, когда тип может использоваться для квалификации идентификатора, то вы, конечно, можете просто использовать имя типа по мере необходимости:

someAlign  := TAlign.alNone;
someMyType := TMyType.alNone;

Это использование перечислений называется scobe enums" и не поддерживается в более старых версиях компилятора Delphi. Я считаю, что XE2 возможно, когда он был введен. Конечно, это была версия, которая сделала обязательные по умолчанию перечисления обязательными по умолчанию.

Хотя его можно отключить с помощью директивы компилятора. Когда вы выключены, вы все равно можете использовать скопированные перечисления, но вам не требуется.

В версиях, которые поддерживают это, вы должны квалифицировать все перечисления, которые определены во время включения. Вы можете выбрать качество или нет при использовании перечислений, которые определены, когда это отключено.

type
{$SCOPEDENUMS ON}
TFoo = (Black, White);  // MUST qualify:  eg. "TFoo.Black"

{$SCOPEDENUMS OFF}
TBar = (Black, White);  // MAY qualify or not if/as needed

Для более старых версий Delphi без поддержки области enum или в ситуациях, когда идентификатор не является членом перечисления и в противном случае не может быть квалифицирован по типу - например, если ваши идентификаторы конфликтуют с некоторым идентификатором на уровне единицы (например, например, mrOk, в Элементы управления), вам нужно немного больше работать, но не много.

В этих случаях просто определите новую константу, чтобы создать однозначный "локальный псевдоним" для константы в другом блоке и ввести это, когда имя единицы однозначно. Похоже на:

  type
    TMyResult = (
      mrOk,
      mrFailed) ;

  const
    Controls_mrOk = Controls.mrOk;  // mrOk is a const, not an enum member