Skip to content

Delphi for .NET namespaces misunderstood?

Confusion

There seems to be a big confusion about Delphi for .NET namespaces. I guess this is because there was a big change between Delphi 8 and Delphi 2005.

In Delphi 8, each unit was its own namespace. In Delphi 2005, several units can be placed in the same namespace, by prefixing the unit name with the namespace name. You can even add to an existing namespace in an assembly not written in Delphi for .NET.

I often see the argument that namespaces in Delphi for .NET are non-standard. But since you can create a namespace consisting of several units, in several assemblies, there is in fact no big difference for other .NET languages. To the "outside" world, i.e. to non-Delphi code, they are as standard as they should be.

IOW, if you have units Rudy.Velthuis.Labels, Rudy.Velthuis.EditBoxes, and Rudy.Velthuis.Memos they make up the namespace Rudy.Velthuis, and can be used as such from any non- Delphi .NET language. (FWIW, if your namespace is only meant to contain VCL.NET classes, I see no reason not to use the VCL terminology, i.e. prefix types with T, etc. If your assembly is meant to be used by other languages, then follow the .NET guidelines on naming.)

What is different is that Delphi for .NET internally has the advantage that you don’t include an entire namespace, filling up the scope with a lot of unnecessary identifiers, but only the units you need. This is IMO a big advantage. If you only need Labels, but not EditBoxes or Memos, you only put Rudy.Velthuis.Labels in your uses clause. I’ll explain why this is IMO a Good Thing™

Any good C++ programmer will frown upon the practice of including entire namespaces into the scope. A good C++ programmer will not use

using namespace std;

but will simply qualify each identifier from that namespace with the explicit std:: prefix. For the same reason, Modula 2 users can import entire modules, but are encouraged to only import the identifiers they need. Delphi for .NET’s scope resolution is not that fine grained, but at least it offers units, instead of the inclusion of entire namespaces. Of course this only works with Delphi-written namespaces.

The fact that namespaces are disconnected from physical file names is perhaps not a problem for a compiler (well, it actually is a small problem, since it makes it have to look up and remember — store — a lot more identifiers, which makes it slower), but it is a problem for the humans who have to use them. I am glad that Delphi keeps the connection between compilation unit and logical unit.

Conclusion

So, to recap:

  • Delphi namespaces are extensible, like in other .NET languages. Several units can make up a namespace, and units can be added to one. They are perhaps non-standard internally, but to the outside .NET world, they are no different than a VB or C# namespace.
  • Delphi namespaces are usable by other languages as one namespace, no matter how many units it contains.
  • Internally, when Delphi uses Delphi-written namespaces, Delphi has the added advantage that you don’t have to include entire namespaces at once, but have a finer grained scoping mechanism.
  • Delphi units are IMO easier to use than namespaces consisting of several source files and spread over several assemblies.

Rudy Velthuis

My quotes.txt file

I have often been asked about the quotes I use when writing to the newsgroups. These come from a file called quotes.txt, and are placed under my messages by my news client, XanaNews, by some kind of random process. Although, sometimes the quotes are so appropriate, that I still suspect that Colin Wilson (the author of XanaNews) has secretly put a small, hidden artificial intelligence machine into the sources.

Anyway, many people have asked me for the quotes file. That is why I decided to publish it on my website. I will attempt to update it regularly.

The format is simple: quotes are free form, and are separated by a lines with a single . character on them. If you enhance the quote file with many new and nice quotes, I’d like you to notify me.

Have fun with it.

Rudy Velthuis

New article on pointers on my website

I wrote a new article on pointers and placed it on my website. Any comments are welcome.

Delphi constructors with different names, when used in C++Builder

The integration of C++Builder and Delphi seems to have caused a few problems for those of us who write components or classes in Delphi, and then want to use these in C++Builder. There are a few things one should avoid when one writes classes (see below), and the symbol BCB doesn’t seem to be defined when the Delphi compiler is called from C++Builder.

Some of the things one should not do are mentioned on the JVCL sourceforge pages.

One other thing is something I discussed elsewhere with someone. In Delphi, it is not unusual to create multiple constructors with different names which tell the user what they do.

A simple example I concocted up is below:

unit GraphicVectors;

interface

uses
  SysUtils, Classes;

type
  TGraphicVector = class(TObject)
  public
    constructor Create(X, Y: Double);
  end;

  TPolarVector = class(TGraphicVector)
  public
    constructor CreatePolar(Radial, Theta: Double);
  end;

implementation

This defines TGraphicVector, which takes two Cartesian coordinates, X and Y, both of type Double. And a descendant TPolarVector, which is internally almost the same, but can be defined using polar coordinates. So TPolarVector has two constructors, the one inherited from TGraphicVector, and CreatePolar, which accepts polar coordinates.

Constructors which differ only in name

Problem is, that both have two parameters of type Double. In Delphi, this is not a problem, because the constructors have different names. But C++ constructors do not have any names of their own. They get the name of the class for which they are defined.

So the .hpp file for the unit above contains this, for TPolarVector:

class DELPHICLASS TPolarVector;
class PASCALIMPLEMENTATION TPolarVector : public TGraphicVector
{
    typedef TGraphicVector inherited;

public:
    __fastcall TPolarVector(double Radial, double Theta);
public:
    #pragma option push -w-inl
    /* TGraphicVector.Create */ inline __fastcall
        TPolarVector(double X, double Y) : TGraphicVector(X, Y) { }
    #pragma option pop

public:
    #pragma option push -w-inl
    /* TObject.Destroy */ inline __fastcall virtual ~TPolarVector(void) { }
    #pragma option pop

};

You can see the problem above: there are two constructors TPolarvector(double, double). The first is TPolarvector.CreatePolar, the second is TGraphicVector.Create, which must be redeclared as TPolarVector to make it a constructor for TPolarVector as well. C++ does not allow two constructors with the same signature, so you will get two errors for the second declaration:

[C++ Error] GraphicVectors.hpp(49): E2238 Multiple declaration for ‘_fastcall TPolarVector::TPolarVector(double,double)’
[C++ Error] GraphicVectors.hpp(46): E2344 Earlier declaration of ‘_fastcall TPolarVector::TPolarVector(double,double)’

Conclusion

So, apart from what the JVCL pages describe, you should also avoid using constructors with the same signature but differing in name. It is best if you simply do not use any other constructor name than Create. If you need more than one, be sure to use the overload directive.

Comments enabled again

In the hope the problems were solved, I enabled comments again.

Blog SPAM

The TeamB blog server has been hit by thousands of blog spam messages (comments/trackbacks). That is why I currently disabled comments, until a solution is found to prevent more of this. Sorry for the inconvenience. :-(

Rudy Velthuis

Quoting in newsgroups

Newsgroups are a great way to communicate. One of the big advantages is, that you don’t have to reply immediately, and that everyone can see your reply. It also means that more than one person can jump into the conversation going on, and write a reply, whenever that person thinks it is convenient to do so. This means that a thread in a newsgroups is not linear or chronological, but can have many sub-branches.

If you scan a newsgroup for a new, unread reply, the reply you find may be a reply to a message made a few days ago, and in a completely different thread or subthread than the message you were reading only a few minutes ago. To remind you of the context of the reply, i.e. to give the reader an indication to what the poster was replying, it is usual to quote (cite) a part of the message to which the reply was made. To make it apparent what was quoted, the quotes are usually marked with a special character, often >, at the start of every line. Many newsreaders allow you to automatically quote the entire previous message when you write a reply. That is of course very convenient for the poster, but it can be a problem for the reader.

If everyone simply quoted the entire previous message (with previous I mean the message to which the reply is made), the final message contains quote over quote of all the previous messages, so more or less the entire thread leading to that point. This may be fine for those who start reading in the middle of a thread, but it wastes an enormous amount of bandwidth, and it gets harder and harder to actually find the actual reply, especially since some people reply at the start of the message (i.e. above the quotes) and some reply below the quotes, or inline, i.e. replying separately to each point made.

In Usenet, a large set of mostly freely available newsgroups shared across many servers around the world, people have tried to define standards for quoting, to avoid this terrible mess. A short version of these (very inofficial) rules, with my personal comments, is:

  • Mark your quotes with a > character. There are different ways of marking a quote, but the > has become some kind of de facto standard, and any other way of quoting makes your replies harder to read, for many people.
  • Reply below the quotes, or inline (which is similar). I know this is a controversial point, but IMO this is the only logical way of replying. Like someone said:

    A: Because it fouls the order in which people normally read text.
    Q: Why is top-posting such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?

    Top-posting is putting your reply above the quotes. One other disadvantage is that someone who expects replies below the quotes, or inline, will have to scroll to the end of the message to see if there is more.

  • Do not overquote. Delete those parts of the quotes which are not necessary to assist the reader in remembering what the previous message was about. If the relation between quotes and new content of a message is grossly in favour of the quotes, one may talk about overquoting. This is a nuisance, since it requires people to read or scroll over a lot of stuff before they see any reply. It also wastes bandwidth, and space on the harddisks of your readers.
  • Do not underquote. If you don’t quote at all, or not enough, the reader does not have a context, and may be forced to re-read the previous message to remember what is going on, or to see to what you are actually replying.

These are my personal views on quoting, and others may have different opinions. But I hope to have given a hint on how newsgroup reading can be made more pleasant. You don’t have to follow my rules, but notice that if you don’t, you might be doing your readers a disservice, and they might decide that they’d rather not read your messages anymore.

Update: I came across this article from a blind person about top-posting. Top-posting seems to confuse a popular newsreader for the blind. One more reason to abandon it, IMO.

Rudy Velthuis

Links

More undocumented Win32 language features

Following up

I received a few interesting replies to my previous post about features Borland implemented in the Win32 compiler for Delphi, but "forgot" to document. I’m sure you can find them in the comments section, but I’d like to repeat them here.

Gerriz Beuze and Rossen Assenov mentioned some other features and I checked them. These seem to be valid in the Win32 personality of Delphi 2005 too:

  • Default array properties can be overloaded, i.e. have the same name, as long as the signature, i.e. the array parameter list, is different.
    type
      TTestClass = class
      private
        function GetInts(index: Integer): Integer;
        procedure SetInts(index: Integer; const Value: Integer);
        function GetIntsS(Find: string): Integer;
        procedure SetIntsS(Find: string; const Value: Integer);
      public
        property Ints[index: Integer]: Integer read GetInts write SetInts;
          default;
        property Ints[Find: string]: Integer read GetIntsS write SetIntsS;
          default;
      end;
    
  • Identifier escape char "&" is supported. You can do something like:
    var
      &object: TObject;
    
  • Method directive "final" supported.
  • Method directive "inline" is supported. But, unlike Gerrit claimed, it also works in .NET.
  • Static class methods are supported.
  • Class properties are supported:
      private
        class function GetClassProp: Integer; static;
        class procedure SetClassProp(const Value: Integer); static;
      public
        class property P: Integer read GetClassProp write SetClassProp;
  • Compiler hint directive "experimental" is supported.
    unit SomeName experimental;
  • Classes support the "abstract" and "sealed" directives.
  • Classes can contain "const", "type" and "var" declarations:
    type
      TAbstract = class abstract
      public
        type
          TTestArray = array of Integer;
          TSealed = class sealed
            procedure DoIt(Param: Integer);
          end;
        const
          Cons = 13;
          ConsB: Integer = 12;
        var
          Y: Integer;
      end;
    

Some more

I found some more features, officially introduced in Delphi 8 and Delphi 2005 for the .NET compiler, which also work in the Win32 personality:

  • Code folding regions:
    {$REGION 'private members'}
      // ...
    {$ENDREGION}

    This is not really a surprise, since they seem to be more an IDE feature than a language feature, but the language must still know them, and not throw an error.

  • Dynamic initialization of dynamic arrays, using the Create syntax:
      type
        TDoubleArray = array of Double;
    
      var
        A: TDoubleArray;
        D: Double;
    
      begin
        A := TDoubleArray.Create(1.7, 3.9, 17.1, 39.7, 42.0);
        for D in A do
          Writeln(D:1:1);
        // etc...
    

    I’m not sure if that is actually documented anywhere, not even for the .NET compiler (where this already worked in Delphi 8, see the KnobControl demo control in the demos that come with Delphi).

But why undocumented?

It seems that some of them are not completely undocumented. The Borland Delphi 2005 Reviewer’s Guide discusses the Win32 compiler (page 59ff.). It mentions function inlining, nested types, strict private, nested consts, support for Pentium 4 SSE3 and SSE2 instruction opcodes and data types, and XML document generation (some of which I hadn’t even noticed). A BDN article by Bob Swart mentions a few new features as well, but for .NET. I tried them in Win32, and they don’t compile.

I’m not sure why the rest is undocumented though, and why Borland is not advertising these new features. Perhaps they were not finalized yet, and Borland doesn’t want to support them, right now. Perhaps they were simply forgotten in the documentation. But the fact that they are undocumented means that you should take extreme care when you use these features. One problem I noticed is with class helpers.

Class helpers

In the previous post, I mentioned class helpers. They do work, but if you try to derive from a "helped" class, you might get an internal compiler error, which means that the implementation is not fully OK yet. Like I said, always use undocumented features with care.

‘Undocumented’ Win32 in Delphi 2005

Yesterday, I was surprised to find out that there are people who don’t know that Delphi 2005 also contains a Win32 personality. Not only does it contain such a personality, the compiler also has a few enhancements I would only have expected in the .NET version.

Class helpers

Class helpers were initially devised to help port Delphi’s Win32 RTL and VCL code to .NET. Using class helpers, Borland was able to map Delphi’s TObject to .NET’s System.Object, and some other Delphi base classes to their .NET equivalent as well, while retaining their Delphi- typical properties and methods. But it seems that class helpers are also available in the Win32 compiler. To me, it is not entirely clear how this could be exploited, but I’m sure that one day, someone will come up with some nifty solution to a problem, using class helpers.

If you want to know how class helpers work, there is a section on them in the online help for Delphi 2005.

Strict private and strict protected

The private and protected sections of Delphi classes were, according to purists, severely flawed, because they did not prevent access to private or protected fields or methods from code in the same unit. The Delphi RTL and VCL actually use this "friend" concept, so it was not so easy to simply remove it.

But in .NET, private and protected really had to be just that, i.e. no other code should have access to these items (except of course descendant classes to protected items). So we got strict private and strict protected sections. Although this is not documented, it seems that these are also available in the Win32 compiler (thanks to Rob Kennedy for finding out). I’m sure that those who have been asking for this for a long time will be pleased to hear this.

Dotted unit names

OK, this feature is not entirely new. Delphi 7 also had it, but it was not documented or enforced there. I specifically call them dotted names, and not namespaces, because AFAIK, the concept of namespaces is still reserved for .NET. Still, I think it makes it easier to name units.

Are there more of these?

If anyone knows more of these undocumented compiler enhancements (also for .NET), I’d love to hear about them, and I will include them in this or a new blog entry.

Warez

Yesterday, I was informed that one or more persons are abusing my name and my TeamB tag on a Russian warez site, to post pirated software there. Of course my first actions were to report this site to Borland, to thank the person warning me, and to inform TeamB.

Everyone with a few working brain cells ought to be able to figure out that no member of TeamB would ever post pirated software on a pirate site. Not only would this be illegal, it would be foolish as well, since we have no personal interest in doing something like that at all. It would thoroughly ruin our good relation with Borland, and our credibility as members of the team.

One other thing to note: members of TeamB only use their TeamB tags on the Borland server. If you see this tag used somewhere else, it was either a mistake, or, much more likely, an impostor.

Bad Behavior has blocked 96 access attempts in the last 7 days.

Close