My favourite (although I don't know if I have ever written code that uses this) is how you can delegate implementation of an interface 'supported' by a class to one of the class's properties. In a pure OO design sense, I don't know if this is awful or beautiful - you're basically lying about what your class's methods are - but in a code cleanliness and separation sense it's awesome. For example (untested, written from memory): type IFoo = interface '{3F996D68-1FD0-4490-AE60-8F735A9DFFE8}' function TheQueensHead: Byte; // Geddit?
They're bars :) function TheBoar: Byte; function TeeFortyTwo: Byte; end; TOnTheTown = class(TInterfacedObject, IFoo) private FFoo: TFoo; // Some class that actually concretely implements IFoo public constructor Create(); property Foo: TFoo read FFoo implements IFoo; // This keyword is the awesome one end; Now, if I remember my Delphi correctly (I mostly use C++ these days) you can call: Party := TOnTheTown.Create(); Party. TheBoar; where TheBoar is shown in the class declaration as implemented by that class, but code-wise you implement it in the class that the property Foo is of - the call is delegated to the property. Neat, isn't it?
Even better, I just learned this very day while googling to check my memory was correct that starting with XE, you can do this in C++ too.
– afrazier May 20 at 14:35 Yes. That's no different to normal. Either declare it as IFoo or, perhaps, cast it (Party as IFoo).
The point is that you have an object that you state implements various methods (because it claims to implement a particular interface) and yet it doesn't - calls are redirected / delegated somewhere else. – David M May 23 at 1:04 Accepted as most awesome feature. – Johan Dec 15 at 13:57.
You can use & to prefix identifiers that would normally be invalid because they are reserved words. Procedure TForm1. Button1Click(Sender: TObject); var &begin, &if, &end: integer; begin &begin := 10; &if := 100; &end := 1000; ShowMessage(IntToStr(&begin + &if + &end)); end.
I see this is in XE, but not in Delphi 7. Was this added so you could have a WSDL method call with Begin as a parameter name? Delphi 7 gives 'illegal character in input file', which is what I expected.
Seems to me they could have added a WSDL rule to prepend an underscore instead. – Warren P May 19 at 19:23 It is there in 2009. The rationale for implementing it, and the exact version in which it first appeared, however, is unknown to me... The docwiki entry.
– Andreas Rejbrand May 19 at 19:27 9 It was introduced with Delphi 8, because it was necessary in order to support the . NET framework without renaming many . NET method names.
– Andreas Hausladen May 19 at 20:59 1 As a C++ programmer, seeing ampersands used like this is just plain weird :) – David M May 20 at 3:34 4 Now you know how we feel about braces, @David. :) The first time I saw C code, I thought, "Why is everything commented out!?" (Didn't help that I opened it in my Pascal editor, so I got Pascal syntax highlighting. ) – Rob Kennedy May 20 at 18:42.
Construct a dynamic array using it's type's constructor: type TInts = array of Integer; .. var Ints: TInts; begin Ints := TInts. Create(3, 5, 1, 0, -2, 5); Not sure if this is documented or not but when I learned this from a newsgroup post after years of using Delphi, I was a bit surprised. PS: Do not Free the array.
:).
2 I think this syntax was added in D2006 or 2007 (it works in 2007, anyway), so the "years" haven't been that long, if it makes you feel better. :) – Ken White May 19 at 22:30 @Ken, thanks, .. also for the mentioned post too! :) – Sertac Akyuz May 19 at 23:23.
You can use the ^A syntax to denote a Ctrl+A 'character': procedure TForm1. FormKeyPress(Sender: TObject; var Key: Char); begin if Key = ^C then ShowMessage('The user wants to copy something. ') else if Key = ^V then ShowMessage('The user wants to paste.') end; Apparently, this is undocumented.
10 I remember reading that in the TurboPascal 4.0 handbook. So it was documented some time ago ;-) – Andreas Hausladen May 19 at 21:01.
Something I have always found a bit funny is the compiler magic associated with the TGUID type. This is declared as TGUID = packed record D1: LongWord; D2: Word; D3: Word; D4: array0..7 of Byte; end; and so, a priori, one would not expect something naïve like const g: TGUID = '{E4C26C63-CDD1-4450-9FE0-6F035E33CF90}'; to work1, but it does. Compiler magic, it is!1 One would expect DCC Error Unit1.
Pas(27): E2010 Incompatible types: 'TGUID' and 'string.
1 There must be some similar compiler magic between TVarRec and "array of const". – Warren P May 19 at 19:18 6 What I love about this feature is how Microsoft foisted this thing called GUIDs on us, and yet, it is only in Delphi that working with them is this "nice and easy". Microsoft makes this crap up.
Delphi makes it almost fun to work with it. – Warren P May 19 at 19:36 5 Even better Pressing + + G inserts a random GUID in your code {virually guaranteed to be unique} (that's a IDE feature and goes with the other question, I know), very handy to have. – Johan May 19 at 20:02 @Warren - yes array of const is converted to the array of TVarRec at compilation, where the compiler tries to convert each member of that array to the corresponding VType type.
This might be posted here as well – user532231 May 20 at 10:32.
The ABSOLUTE keyword This is a nice way to shoot yourself in the foot, because it throws type-safety out the window big time. Delphi's RTL sources uses this in 5 different units. The first 4 only use it once per unit, then there's Mxarrays.
Pas where this is used 22 times. What I'm trying to say is that the absolute keyword is rarely used. // This is how it's useful: procedure Test; var i64: Int64; b:array0..7 of Byte absolute i64; // starts at the same memory space as i64 begin i64 := 7; WriteLn(b3); end; // This is how you shoot yourself in the foot: procedure Test; var s: string; i: NativeInt absolute s; begin s := 'Test'; Dec(i, 7); ShowMessage(s); // will give you garbage or AV end.
3 Jolyon Smith wrote an interesting article about absolute: Absolute (for) Beginners. – Ulrich Gerhardt May 20 at 9:58 1 I could write it shorter. Absolute for Beginners; Just Don't do it!
– Warren P May 21 at 1:29.
Variant Records Variant records are weired-looking records where some part of the record is "variable". Every time I see one used I say That's an useful trick, but never managed to actually use one in my own code. And I do use weired unsafe things like the absolute keyword and pointer arithmetic.
Example: type TKindOfShape = (ksCircle, ksSquare); Shape = record case Kind:TKindOfShape of ksCircle: ( R: Double; CenterX, CenterY: Double; ); ksSquare: ( Top, Left, SideSize: Double; ); end.
Not so much hidden, as ancient are the digraphs supported by the original Wirth pascal, which still work in Delphi: procedure Dummy; var a:array (. 0 .. 2 . ) of Integer; begin end; The character sequence (. and . ) replace and on systems where the and are not even available, and are called digraphs because they are two characters.
C/C++ for example, supports some Trigraphs (three character symbols), too. I think most Delphi programmers have seen comments that are written with (* and *) which are the common digraph form of { and }.
8 (* and *) are especially useful for commenting out pieces of code that already contain { } comments. – GolezTrol May 19 at 18:45 Yep. That's what I use 'em for.
– Warren P May 19 at 18:46 I'm currently translating some C# to Delphi - great to be able to paste in C#, then surround with (* *) – Gerry Coll May 20 at 3:53.
It is possible to omit the parameter list of routines that are declared in the interface section. For functions it is even possible to omit the result type, which leads to weird looking implementations like: function GetText(var A: Integer; const B: Char; C: Word = 0): String; implementation function GetText; begin Result := 'Where am I going? '; end; Obviously, this does not apply to overloaded routines.
;) Sometimes when someone else's code passes by, this is still surprising. Users would have maintenance reasons.
3 never understood the need for this feature it just makes stuff harder to read and understand. And with autocomplete it doesn't even save any typing. – Johan May 22 at 9:42 1 For functions it is even possible to omit the result type – if you are omitting the parameters, you must omit the result type too.
Otherwise the compiler will think the implementation doesn't match the declaration. – Andriy M May 26 at 7:42 Well, my point mainly was pointing out the weirdness, hence the phrase syntax. But good remark!
+1 – NGLN May 26 at 7:47.
Almost everyone knows about the increment and decrement function: Inc(N) - to increment N by 1. Dec(N) - to decrement N by 1. But did you know they have a second parameter, which is the amount of the increment? Inc(N, I) - to increment N by I.
Dec(N, D) - to decrement N by D. Now I think these are for people who start using Delphi after using other languages. Personally I prefer: N := N + 1; N := N - 1; N := N + I; N := N - D; which generates exactly the same code as Inc and Dec do, with equivalent optimizations.
Don't forget about Pred and Succ, which when applied to integers returns the value one less and one greater without changing the original value. And you can string them, e.g. Pred(Pred(Pred(N))).
5 Till recently, the + and - operators didn't work on pointer types (except character-pointer types), so Inc and Dec were the type-safe way of doing pointer arithmetic. People can also prefer using Inc so avoid having to write the variable name twice (although that doesn't work for properties). – Rob Kennedy May 19 at 23:53.
Example: function CryptReleaseContext(hProv: HCRYPTPROV; dwFlags: DWORD): BOOL; winapi; This is fully equivalent to: function CryptReleaseContext(hProv: HCRYPTPROV; dwFlags: DWORD): BOOL; stdcall.
Wow, it does too. It works with syntax highlighting and everything. The documentation doesn't mention it at all... – David M May 23 at 6:22 I suppose that's the equivalent of windef.
H's #define WINAPI __stdcall. – David M May 23 at 6:26.
I always seem to forget about Method Overloading. Multiple routines can share the same name. The number of parameters and type of each parameter determine which will be called.E.g.
: Function Multiply (A, B: integer): integer; overload; Function Multiply (A, B: double): double; overload; Early Delphi users might not know about this one because it was added in Delphi 4. See: delphibasics.co.uk/RTL.asp?Name=Overload.
1 That's not a hack, but a standard compiler feature. – Mihaela May 20 at 13:17 @Mihaela: I never said it was a hack. It's just a feature I would consider hidden and often overlooked.
– lkessler May 20 at 13:32 3 Function overloading is something most Delphi developers learn early, in my experience. – Andreas Rejbrand May 20 at 17:34 I know about it, and tend to avoid it whenever I think it might confuse other people. – Warren P May 200 at 1:31.
There is a nice list of new Delphi language features added since Delphi 7, along with good examples of each at: edn.embarcadero.com/article/34324 It includes: Inlining Operator Overloading Class Helpers Strict Private Strict Protected Records with Methods Class abstract Class sealed Class const Class type Class var Class property Nested classes Final methods Sealed methods Static class methods, and For-in loop.
Especially when they're widely promoted as a way of saying 'hey, look what we've added since D7, upgrade now! ' I think the OP was asking more about things that you might not know about or are rarely used. – David M May 20 at 3:33 2 @David: Yes, initially we hear about the new features.
But most often, we don't try using them right away and then forget about them and go back to what we know. I bet if you go through this list, there will be few of them you've tried using, and many that you don't even recall hearing of. I would classify these as hidden from most people.
– lkessler May 20 at 4:27 1 A good list of new language features can also be found at tindex.net. – gabr May 20 at 6:57 I thought I'd seen them all but that TIndex is a great new site for Delphi programmers. Thanks for the link @Gabr!
– lkessler May 20 at 13:02.
The ; is used to separate statements, not end statements, so you actually don't need the last ; before end: procedure DoNothing; begin Inc(i); Dec(i) end; It is more convenient to add statements and move statements when they all end with the ;, so I definitely wouldn't recommend to implement this a new practice at the workplace :).
Thanks for pointing this out @Jørn. I learned this the puzzling way when I inadvertently left a semicolon off and wondered WTF, why did it still compile? – lkessler May 20 at 13:13 1 Interesting and explanatory feature, but not very useful.
;) – NGLN May 22 at 7:25 I had a boss at one place I worked that insisted that the ; on the last line of a method be removed. Incredibly frustrating! Especially if he did a code review after I had written a couple of thousand lines of code!
– Nat May 23 at 9:57.
Since Delphi 6, you can declare external functions like wsprintf using the varargs directive. *) This will allow setting a variable number of parameters, in exactly the same way as in C/C++ function wsprintf(lpOut, lpFmt: PChar): Integer; cdecl; varargs; For normal Delphi routines this is not needed because you can use open arrays, but for compatibility with C/C++ this is a nice feature to have. Make sure to set the calling convention to cdecl.
*) Source: rvelthuis.de/articles/articles-convert.h....
Which is why it was added btw, for Kylix' sake – Marco van de Voort May 22 at 14:34.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.