【问题标题】:Delphi - How do you resolve a conflict when a unit name is the same as a property name?Delphi - 当单位名称与属性名称相同时,如何解决冲突?
【发布时间】:2017-03-16 21:18:35
【问题描述】:

下面的简单示例是我试图解决冲突的一个问题的缩影,其中我有一个与 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 是我声明的,而不是 Controls.pas 中定义的 TAlign 成员。
  • 第二个失败,因为 Controls 表示该名称的 TForm 属性。

我意识到有办法解决这个问题(重命名 alNone 成员是最简单的),但我很好奇是否有办法限定对另一个单元中的属性的引用,其中 unit名称 与当前范围内的标识符冲突。

【问题讨论】:

    标签: delphi scope delphi-2007


    【解决方案1】:

    使用类型名称对其进行限定:

    TAlign.alNone
    

    当我写这篇文章时,我没有意识到编译器版本是相关的。此语法仅在 Delphi 2010 或 XE 中可用。那里的答案不适合标记版本 Delphi 2007。 Deltics 的答案涵盖了更多细节。

    【讨论】:

    • 我个人总是这样写枚举类型。更有意义、更常见(跨不同语言)。
    • @ross - 你是如何用 D2007 做到这一点的?我抱怨 "[DCC Error] Unit1.pas(33): E2018 Record, object or class type required".
    • 这很有趣,我确信语法总是可用的,但你说的很对
    • @Sertac - 我已经通过选择一个不冲突的名称解决了这个问题,并且没有尝试使用类型名称对其进行限定。
    【解决方案2】:

    正如大卫的回答所暗示的那样,对于枚举类型或其他可以使用类型来限定所涉及的标识符的情况,那么您当然可以根据需要简单地使用类型名称:

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

    枚举的这种用法称为“scoped 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,或者在标识符 不是 一个枚举成员并且不能按类型限定的情况下 - 例如,如果您的标识符与某些 冲突单位级别的标识符(例如mrOk,在Controls中)那么你需要做更多的工作,但不多。

    在这些情况下,只需定义一个新常量,为其他单元中的常量创建一个明确的“本地别名”,并在单元名称明确的地方引入它。类似于:

      type
        TMyResult = (
          mrOk,
          mrFailed) ;
    
      const
        Controls_mrOk = Controls.mrOk;  // mrOk is a const, not an enum member
    

    【讨论】:

    • XE 允许 TAlign.alNone,2007 不允许。文档可以追溯到2010。可能是 XE 或 2010 年。
    猜你喜欢
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 2020-02-04
    相关资源
    最近更新 更多