Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi - How do you resolve a conflict when a unit name is the same as a property name?

The trivial example below is a condensation of a problem I had trying to resolve a conflict where I had an enumerated type member with the same name as a VCL member.

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.
  • The first assignment fails because the compiler thinks alNone is the one I declared and not the TAlign member defined in Controls.pas.
  • The second one fails because it took Controls to mean the TForm property of that name.

I realise there are ways around this (renaming the alNone member being the simplest), but I'm curious as to whether there is a way of qualifying a reference to a property in another unit where the unit name conflicts with an identifier in the current scope.

like image 421
rossmcm Avatar asked Mar 16 '17 21:03

rossmcm


People also ask

How do I resolve a conflict between two GitHub Pages?

The easiest way to resolve a conflict is to change the file on your computer. If you open README.md now, you’ll see lines that say this: <<<<<< HEAD Hello world! This is my third Github repo!====== Hello world! This is my second Github repo! >>>>>> snt2h1s3n4tnthd9au8d3324

How do you resolve a conflict between two parties?

Compromising Also known as reconciling, compromising seeks a mutual agreement to settle a dispute. Both parties willingly forfeit some of their conditions in the interest of reaching an agreement. This can be a quick way to resolve a conflict without it becoming a bigger issue.

How do I Fix two lines of code that are conflicting?

These two lines of code are conflicting. We need to choose between the “second Github repo” or the “third Github repo”. To fix the conflict, you choose the correct line of code. Then you delete everything else. In this case, let’s say “third” is the correct version. What you’ll do is delete everything else that’s incorrect. Hello world!

Is there an IDE fix for cannot resolve unit XYZ?

There is an IDE Fix Pack developed by Andreas Hausladen which reduces the number of those "Cannot resolve unit xyz" problems. It doesn't fix the bug, but it makes them less visible by addressing some of the Error Insight's threading problems. Show activity on this post.


2 Answers

Qualify it with the type name:

TAlign.alNone

I had not realised when I wrote this that the compiler version was relevant. This syntax only became available in Delphi 2010 or XE. There the answer is not appropriate for the tagged version, Delphi 2007. Deltics answer covers much more detail.

like image 58
David Heffernan Avatar answered Oct 25 '22 21:10

David Heffernan


As David's answer suggests, for an enum type or other situation where a type can be used to qualify the identifier involved then you can of course simply use the type name as required:

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

This use of enums is referred to as "scoped enums" and is not supported in older versions of the Delphi compiler. I believe XE2 may have been when it was introduced. Certainly this was the version that made scoping enums in this way mandatory by default.

Though it can be turned off via a compiler directive. When turned off, you can still use scoped enums but you are not required to.

In versions that support this, you must qualify any enums that are defined while this is turned on. You can choose whether to quality or not when using enums that are defined when this is turned off.

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

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

For older versions of Delphi without scoped enum support, or in situations where the identifier is not an enum member and cannot otherwise be qualified by type - for example if your identifiers conflict with some unit-level identifier (e.g. such as mrOk, in Controls) then you need to a little bit more work, but not much.

In these cases, simply define a new constant to create an unambiguous "local alias" for the constant in the other unit, and introduce this where the unit name is unambiguous. Similar to:

  type
    TMyResult = (
      mrOk,
      mrFailed) ;

  const
    Controls_mrOk = Controls.mrOk;  // mrOk is a const, not an enum member
like image 35
Deltics Avatar answered Oct 25 '22 19:10

Deltics