<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:gr="http://www.google.com/schemas/reader/atom/" xmlns:idx="urn:atom-extension:indexing" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" idx:index="no" gr:dir="ltr"><!--
Content-type: Preventing XSRF in IE.

--><generator uri="http://www.google.com/reader">Google Reader</generator><id>tag:google.com,2005:reader/user/07946391749317373099/state/com.google/broadcast</id><title>Jamie's shared items in Google Reader</title><gr:continuation>CI29n_Ow6qEC</gr:continuation><author><name>Jamie</name></author><updated>2010-09-07T08:56:34Z</updated><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/JamiesDelphiClippings" /><feedburner:info uri="jamiesdelphiclippings" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gr:crawl-timestamp-msec="1283849794983"><id gr:original-id="tag:blogger.com,1999:blog-10106032.post-8978022569059153657">tag:google.com,2005:reader/item/09c37fed30d11be9</id><title type="html">Virtual method interception</title><published>2010-09-01T11:00:00Z</published><updated>2010-09-06T17:26:06Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/yD2b7s9tETo/virtual-method-interception.html" type="text/html" /><link rel="replies" href="http://blog.barrkel.com/feeds/8978022569059153657/comments/default" title="Post Comments" type="application/atom+xml" /><link rel="replies" href="https://www.blogger.com/comment.g?blogID=10106032&amp;postID=8978022569059153657" title="11 Comments" type="text/html" /><content xml:base="http://blog.barrkel.com/" type="html">&lt;p&gt;&lt;a href="http://www.embarcadero.com/rad-studio-xe-preview"&gt;Delphi XE&lt;/a&gt; has a new type in Rtti.pas called TVirtualMethodInterceptor. It was originally designed for use in DataSnap authentication scenarios (though I don't think it's currently being used there), but of course, making it only work for that would have been quite a limitation.&lt;/p&gt;

&lt;p&gt;What does it do? Essentially, it creates a derived metaclass dynamically at runtime that overrides every virtual method in the ancestor, by creating a new virtual method table and populating it with stubs that intercepts calls and arguments. When the metaclass reference for any instance of the "ancestor" is replaced with this new metaclass, the user can then intercept virtual function calls, change arguments on the fly, change the return value, intercept and suppress exceptions or raise new exceptions, or entirely replace calling the underlying method. In concept, it's somewhat similar to dynamic proxies from &lt;a href="http://www.codeproject.com/KB/dotnet/dynamicproxy.aspx"&gt;.NET&lt;/a&gt; and &lt;a href="http://www.devx.com/Java/Article/21463"&gt;Java&lt;/a&gt;. It's like being able to derive from a class at runtime, override methods (but not add new instance fields), and then change the runtime type of an instance to this new derived class.&lt;/p&gt;

&lt;p&gt;Why would you want to do this? Two obvious purposes spring to mind: testing and remoting. Mock objects have been in vogue in the testing space in other languages for some time. By intercepting method calls, one may more easily verify that a particular subsystem is calling all the right methods, with the correct arguments, in the expected order; similarly, the subsystem can proceed with the return values from these method calls, without necessarily having to hit the database, the network, etc. for what should be a unit test. Remoting on the basis of method calls is somewhat less useful, especially when an unreliable and latency-prone network gets into the stack, but that's not the only usage point. The virtual method interceptor logic was originally implemented to be used as part of DataSnap authentication, so that a call that comes in from the network can still be checked as its code flow spreads throughout the graph of objects.&lt;/p&gt;

&lt;p&gt;Anyhow, here's a simple example to get started:&lt;/p&gt;

&lt;pre&gt;
uses SysUtils, Rtti;
{$apptype console}
type
  TFoo = class
    // Frob doubles x and returns the new x + 10
    function Frob(var x: Integer): Integer; virtual;
  end;

function TFoo.Frob(var x: Integer): Integer;
begin
  x := x * 2;
  Result := x + 10;
end;

procedure WorkWithFoo(Foo: TFoo);
var
  a, b: Integer;
begin
  a := 10;
  Writeln(&amp;#39;  before: a = &amp;#39;, a);
  try
    b := Foo.Frob(a);
    Writeln(&amp;#39;  Result = &amp;#39;, b);
    Writeln(&amp;#39;  after:  a = &amp;#39;, a);
  except
    on e: Exception do
      Writeln(&amp;#39;  Exception: &amp;#39;, e.ClassName);
  end;
end;

procedure P;
var
  foo: TFoo;
  vmi: TVirtualMethodInterceptor;
begin
  vmi := nil;
  foo := TFoo.Create;
  try
    Writeln(&amp;#39;Before hackery:&amp;#39;);
    WorkWithFoo(foo);
    
    vmi := TVirtualMethodInterceptor.Create(foo.ClassType);
    
    vmi.OnBefore := procedure(Instance: TObject; Method: TRttiMethod;
      const Args: TArray&amp;lt;TValue&amp;gt;; out DoInvoke: Boolean; out Result: TValue)
    var
      i: Integer;
    begin
      Write(&amp;#39;[before] Calling &amp;#39;, Method.Name, &amp;#39; with args: &amp;#39;);
      for i := 0 to Length(Args) - 1 do
        Write(Args[i].ToString, &amp;#39; &amp;#39;);
      Writeln;
    end;
    
    // Change foo&amp;#39;s metaclass pointer to our new dynamically derived
    // and intercepted descendant
    vmi.Proxify(foo);
    
    Writeln(&amp;#39;After interception:&amp;#39;);
    WorkWithFoo(foo);
  finally
    foo.Free;
    vmi.Free;
  end;
end;

begin
  P;
end.
&lt;/pre&gt;

&lt;p&gt;Here's what it outputs:&lt;/p&gt;

&lt;pre&gt;
Before hackery:
  before: a = 10
  Result = 30
  after:  a = 20
After interception:
  before: a = 10
[before] Calling Frob with args: 10 
  Result = 30
  after:  a = 20
[before] Calling BeforeDestruction with args: 
[before] Calling FreeInstance with args: 
&lt;/pre&gt;

&lt;p&gt;You'll notice that it intercepts all the virtual methods, including those called during destruction, not just the one I declared. (The destructor itself is not included.)&lt;/p&gt;

&lt;p&gt;We can get more ambitious with what it does. I can change the implementation entirely, and skip calling the underlying (i.e. inherited) method body:&lt;/p&gt;

&lt;pre&gt;
procedure P;
var
  foo: TFoo;
  vmi: TVirtualMethodInterceptor;
  ctx: TRttiContext;
  m: TRttiMethod;
begin
  vmi := nil;
  foo := TFoo.Create;
  try
    Writeln('Before hackery:');
    WorkWithFoo(foo);
    
    vmi := TVirtualMethodInterceptor.Create(foo.ClassType);
    
    m := ctx.GetType(TFoo).GetMethod('Frob');
    vmi.OnBefore := procedure(Instance: TObject; Method: TRttiMethod;
      const Args: TArray; out DoInvoke: Boolean; out Result: TValue)
    begin
      if Method = m then
      begin
        DoInvoke := False;
        Result := 42;
        Args[0] := -Args[0].AsInteger;
      end;
    end;
&lt;/pre&gt;

&lt;p&gt;Here, I inhibit the invocation and hard-code the result to 42, while negating the first argument. The proof is in the output:&lt;/p&gt;

&lt;pre&gt;
Before hackery:
  before: a = 10
  Result = 30
  after:  a = 20
After interception:
  before: a = 10
  Result = 42
  after:  a = -10
&lt;/pre&gt;

&lt;p&gt;I could have inhibited the call by raising an exception instead:&lt;/p&gt;

&lt;pre&gt;
    vmi.OnBefore := procedure(Instance: TObject; Method: TRttiMethod;
      const Args: TArray; out DoInvoke: Boolean; out Result: TValue)
    begin
      if Method = m then
        raise Exception.Create('Aborting');
    end;
&lt;/pre&gt;

&lt;p&gt;And output:&lt;/p&gt;

&lt;pre&gt;
Before hackery:
  before: a = 10
  Result = 30
  after:  a = 20
After interception:
  before: a = 10
  Exception: Exception
&lt;/pre&gt;

&lt;p&gt;It's not limited to interception before the logically inherited call, but also interception after the call, again with the opportunity to fiddle with arguments and return value:&lt;/p&gt;

&lt;pre&gt;
    m := ctx.GetType(TFoo).GetMethod('Frob');
    vmi.OnAfter := procedure(Instance: TObject; Method: TRttiMethod;
      const Args: TArray; var Result: TValue)
    begin
      if Method = m then
        Result := Result.AsInteger + 1000000;
    end;
&lt;/pre&gt;

&lt;p&gt;And output:&lt;/p&gt;

&lt;pre&gt;
Before hackery:
  before: a = 10
  Result = 30
  after:  a = 20
After interception:
  before: a = 10
  Result = 1000030
  after:  a = 20
&lt;/pre&gt;

&lt;p&gt;And if the inherited implementation raises an exception, that can even be squashed:&lt;/p&gt;

&lt;pre&gt;
function TFoo.Frob(var x: Integer): Integer;
begin
  raise Exception.Create('Abort');
end;

// ...
    m := ctx.GetType(TFoo).GetMethod('Frob');
    vmi.OnException := procedure(Instance: TObject; Method: TRttiMethod;
      const Args: TArray; out RaiseException: Boolean;
      TheException: Exception; out Result: TValue)
    begin
      if Method = m then
      begin
        RaiseException := False;
        Args[0] := Args[0].AsInteger * 2;
        Result := Args[0].AsInteger + 10;
      end;
    end;
&lt;/pre&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;pre&gt;
Before hackery:
  before: a = 10
  Exception: Exception
After interception:
  before: a = 10
  Result = 30
  after:  a = 20
&lt;/pre&gt;

&lt;p&gt;One thing the TVirtualMethodInterceptor class doesn't have, however, is a way to unhook (unproxify) the object. If the object is never unhooked, it's important that the object doesn't outlive the interceptor, because the interceptor needs to allocate executable memory in order to create the little stubs with which it redirects method calls to the events. Fortunately, it's pretty trivial to do:&lt;/p&gt;

&lt;pre&gt;
    PPointer(foo)^ := vmi.OriginalClass;
&lt;/pre&gt;

&lt;p&gt;Another point: the class inheritance chain is changed by the hooking process. This can be shown easily:&lt;/p&gt;

&lt;pre&gt;
//...
    Writeln(&amp;#39;After interception:&amp;#39;);
    WorkWithFoo(foo);
    
    Writeln(&amp;#39;Inheritance chain while intercepted:&amp;#39;);
    cls := foo.ClassType;
    while cls &amp;lt;&amp;gt; nil do
    begin
      Writeln(Format(&amp;#39;  %s (%p)&amp;#39;, [cls.ClassName, Pointer(cls)]));
      cls := cls.ClassParent;
    end;
    
    PPointer(foo)^ := vmi.OriginalClass;
    
    Writeln(&amp;#39;After unhooking:&amp;#39;);
    WorkWithFoo(foo);
    
    Writeln(&amp;#39;Inheritance chain after unhooking:&amp;#39;);
    cls := foo.ClassType;
    while cls &amp;lt;&amp;gt; nil do
    begin
      Writeln(Format(&amp;#39;  %s (%p)&amp;#39;, [cls.ClassName, Pointer(cls)]));
      cls := cls.ClassParent;
    end;
// ...
&lt;/pre&gt;

&lt;p&gt;And output:&lt;/p&gt;

&lt;pre&gt;
Before hackery:
  before: a = 10
  Exception: Exception
After interception:
  before: a = 10
  Result = 30
  after:  a = 20
Inheritance chain while intercepted:
  TFoo (01F34DA8)
  TFoo (0048BD84)
  TObject (004014F0)
After unhooking:
  before: a = 10
  Exception: Exception
Inheritance chain after unhooking:
  TFoo (0048BD84)
  TObject (004014F0)
&lt;/pre&gt;

&lt;p&gt;The feature is primarily an infrastructure piece for advanced libraries, but hopefully you can see that it's not too difficult to get into.&lt;/p&gt;&lt;div&gt;&lt;img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/10106032-8978022569059153657?l=blog.barrkel.com" alt=""&gt;&lt;/div&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/EntropyOverload?a=j_WNWK25IEU:K53FCMMg12Q:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/EntropyOverload?d=cGdyc7Q-1BI" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/EntropyOverload?a=j_WNWK25IEU:K53FCMMg12Q:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/EntropyOverload?i=j_WNWK25IEU:K53FCMMg12Q:4cEx4HpKnUU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/EntropyOverload?a=j_WNWK25IEU:K53FCMMg12Q:UT3xtbGYFzA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/EntropyOverload?d=UT3xtbGYFzA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/EntropyOverload?a=j_WNWK25IEU:K53FCMMg12Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/EntropyOverload?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/EntropyOverload/~4/j_WNWK25IEU" height="1" width="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/yD2b7s9tETo" height="1" width="1"/&gt;</content><author><name>Barry Kelly</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/EntropyOverload"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/EntropyOverload</id><title type="html">Entropy Overload</title><link rel="alternate" href="http://blog.barrkel.com/" type="text/html" /></source><feedburner:origLink>http://feedproxy.google.com/~r/EntropyOverload/~3/j_WNWK25IEU/virtual-method-interception.html</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1283504004063"><id gr:original-id="http://www.finalbuilder.com/Resources/Blogs/tabid/458/EntryId/282/Getting-Started-with-Delphi-XEs-Regular-Expressions.aspx">tag:google.com,2005:reader/item/9403b8c586ba7c65</id><title type="html">Getting Started with Delphi XE's Regular Expressions</title><published>2010-09-02T14:00:00Z</published><updated>2010-09-02T14:00:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/8wFmOdyL5Ws/Getting-Started-with-Delphi-XEs-Regular-Expressions.aspx" type="text/html" /><summary xml:base="http://www.finalbuilder.com/" type="html">&lt;p&gt;Delphi XE includes Regular Expression support, something that has been requested many times over the years. In this blog post I'll show some basic usage of regular expressions in delphi.&lt;/p&gt;&lt;a href="http://www.finalbuilder.com/Resources/Blogs/tabid/458/EntryId/282/Getting-Started-with-Delphi-XEs-Regular-Expressions.aspx"&gt;More...&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/8wFmOdyL5Ws" height="1" width="1"/&gt;</summary><author><name>vincent@finalbuilder.com</name></author><source gr:stream-id="feed/http://www.finalbuilder.com/RSS.aspx?tabid=77&amp;moduleid=398"><id>tag:google.com,2005:reader/feed/http://www.finalbuilder.com/RSS.aspx?tabid=77&amp;moduleid=398</id><title type="html">VSoft Technologies</title><link rel="alternate" href="http://www.finalbuilder.com" type="text/html" /></source><feedburner:origLink>http://www.finalbuilder.com/Resources/Blogs/tabid/458/EntryId/282/Getting-Started-with-Delphi-XEs-Regular-Expressions.aspx</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1283333154649"><id gr:original-id="http://andy.jgknet.de/blog/?p=870">tag:google.com,2005:reader/item/287a592d69171411</id><category term="Delphi" /><title type="html">How to tune Delphi XE’s start up</title><published>2010-08-31T17:41:29Z</published><updated>2010-08-31T17:41:29Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/oTrboxGNyIk/" type="text/html" /><content xml:base="http://andy.jgknet.de/blog" type="html">&lt;p style="text-align:justify"&gt;When I started Delphi XE today the first time, I recognized a 6 second delay when it shows “IDE Packages loaded” in the splash screen. On the second start it still shows “IDE Packages loaded” for 5 seconds. Because I wanted to know what the IDE does in those 5 seconds with 100% CPU load (25% on my 4 CPU machine), I debugged the IDE with an empty IDEFixPack for Delphi XE project (sorry no bug fixes yet  &lt;img src="http://andy.jgknet.de/blog/wp-includes/images/smilies/icon_mrgreen.gif" alt=":mrgreen:"&gt;   ). I pressed the Pause-Button when it reached the delay.&lt;/p&gt;
&lt;p style="text-align:justify"&gt;The function that I saw in the call stack was the TStrings.IndexOfName method that was called by TStrings.SetValue. The string list contained about 3000 items. All of them were files in $(BDS)\source. That means that something enumerates all source file names and put them in the string list in the format “filename=path”. Returning from TStrings.SetValue showed me the IDE plugin that is responsible for the startup delay: Beyond Compare. The IDE plugin seems to cache file locations. I don’t know why it needs the location of all source files, &lt;strong&gt;but not on my computer&lt;/strong&gt;. I have removed BC from the “Experts” registry key and now my IDE starts much faster.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p style="text-align:justify"&gt;BTW: &lt;a href="http://andy.jgknet.de/blog/?p=855"&gt;Don’t forget to disable the Component-Toolbar package&lt;/a&gt; if you want to switch faster from Code to Design view.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/oTrboxGNyIk" height="1" width="1"/&gt;</content><author><name>Andreas Hausladen</name></author><source gr:stream-id="feed/http://andy.jgknet.de/blog/?feed=rss2"><id>tag:google.com,2005:reader/feed/http://andy.jgknet.de/blog/?feed=rss2</id><title type="html">Andy&amp;#39;s Blog and Tools</title><link rel="alternate" href="http://andy.jgknet.de/blog" type="text/html" /></source><feedburner:origLink>http://andy.jgknet.de/blog/2010/08/how-to-tune-delphi-xes-start-up/</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1283333153787"><id gr:original-id="http://www.danieleteti.it/?p=250">tag:google.com,2005:reader/item/9d082e391bba42c0</id><category term="Design Patterns" /><category term="Programming" /><category term="RTTI" /><category term="Delphi" /><category term="DORM" /><title type="html">Sneak preview about DORM, The Delphi ORM</title><published>2010-09-01T08:17:04Z</published><updated>2010-09-01T08:17:04Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/alZF0gVOdnU/" type="text/html" /><content xml:base="http://www.danieleteti.it/" type="html">&lt;p&gt;My yesterday post about this busy time, have raised some interest about DORM, the Delphi ORM.&lt;/p&gt;
&lt;p&gt;So, also if I still haven’t released any files, wish to expose some internals about DORM.&lt;/p&gt;
&lt;p&gt;DORM is an implementation of the &lt;a href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;DataMapper&lt;/a&gt; design pattern written having &lt;a href="http://hibernate.org/"&gt;Hibernate&lt;/a&gt; in mind.&lt;/p&gt;
&lt;p&gt;It’s completely unit tested and have the following features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;External file mapping. (JSON format)
&lt;li&gt;Persistence ignorance (every TObject can be persisted)
&lt;li&gt;Support for One-One and One-Many relations (still no many-many)
&lt;li&gt;Support for LazyLoading (you can enable§/disable lazyloading by file or by code by per-basis needs)
&lt;li&gt; Support for IdentityMap
&lt;li&gt; Support for custom “finder” (you can still use complex SQL if you want)
&lt;li&gt; Complete support for CRUD
&lt;li&gt; Transactions
&lt;li&gt; Built in logging system to log *EVERY* sql or action performed by the framework
&lt;li&gt; Opened to multiple data access strategies (interfaced based, not inheritance based) for use with different database (now I’ve developed the firebird one using DBX)
&lt;li&gt; Caching for RTTI (the TSession object have a single TRttiContext holding ALL metadata)
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Code is still under heavely development.&lt;/p&gt;
&lt;p&gt;Those are 2 test-method to show the use of DORM:&lt;/p&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;TPerson &lt;span&gt;=&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TObject&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;…&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;property&lt;/span&gt; Phones&lt;span&gt;:&lt;/span&gt; TdormCollection&lt;span&gt;….&lt;/span&gt; &lt;span&gt;//implements IList&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;TPhone &lt;span&gt;=&lt;/span&gt; classs&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TObject&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;…&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;//and now the unit tests&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;procedure&lt;/span&gt; TTestDORMHasMany&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Setup&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;begin&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  Session &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; TSession&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Create&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Configure&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;TStreamReader&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;#39;dorm.conf&amp;#39;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;procedure&lt;/span&gt; TTestDORMHasMany&lt;span&gt;.&lt;/span&gt;&lt;span&gt;TearDown&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;begin&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Free&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;procedure&lt;/span&gt; TTestDORMHasMany&lt;span&gt;.&lt;/span&gt;&lt;span&gt;TestHasManyLazyLoad&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;var&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  p&lt;span&gt;:&lt;/span&gt; TPerson&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  t&lt;span&gt;:&lt;/span&gt; TPhone&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  guid&lt;span&gt;:&lt;/span&gt; &lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;begin&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  p &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; TPerson&lt;span&gt;.&lt;/span&gt;&lt;span&gt;NewPersona&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;//static method. Return a fully populated TPerson object&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;try&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    t &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; TPhone&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Create&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    p&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Phones&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;t&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Save&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;p&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    guid &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; p&lt;span&gt;.&lt;/span&gt;&lt;span&gt;guid&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;//GUIDs, or other PK types, are generated automagically by DORM. Obviously there is a specific class loaded to do this specified in the dorm.conf file)&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;finally&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Commit&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StartTransaction&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;// Test with lazy load ON&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetLazyLoadFor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TypeInfo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;TPerson&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;&amp;#39;Phones&amp;#39;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  p &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Load&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TypeInfo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;TPerson&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; guid&lt;span&gt;)&lt;/span&gt; &lt;span&gt;as&lt;/span&gt; TPerson&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;try&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    CheckEquals&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; p&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Phones&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Count&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;finally&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Commit&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StartTransaction&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;// Test with lazy load OFF&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetLazyLoadFor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TypeInfo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;TPerson&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;&amp;#39;Phones&amp;#39;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;false&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  p &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Load&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TypeInfo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;TPerson&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; guid&lt;span&gt;)&lt;/span&gt; &lt;span&gt;as&lt;/span&gt; TPerson&lt;span&gt;;&lt;/span&gt; &lt;span&gt;// Without commit, AV becouse IdentityMap doesn&amp;#39;t work properly&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;try&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    CheckEquals&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; p&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Phones&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Count&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt; &lt;span&gt;// Child objects are loaded&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;finally&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Commit&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;procedure&lt;/span&gt; TTestDORMHasMany&lt;span&gt;.&lt;/span&gt;&lt;span&gt;TestLoadHasMany&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;var&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  list&lt;span&gt;:&lt;/span&gt; IList&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  t&lt;span&gt;,&lt;/span&gt; t1&lt;span&gt;:&lt;/span&gt; TPhone&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  p&lt;span&gt;:&lt;/span&gt; TPerson&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  guid&lt;span&gt;:&lt;/span&gt; &lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;begin&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  p &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; TPerson&lt;span&gt;.&lt;/span&gt;&lt;span&gt;NewPersona&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;//static method. Return a fully populated TPerson object&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;try&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    t &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; TPhone&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Create&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    t&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Numero&lt;/span&gt; &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;&amp;#39;555-7765123&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    t&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Kind&lt;/span&gt; &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;&amp;#39;Casa&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    p&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Phones&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;t&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    t1 &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; TPhone&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Create&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    t1&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Number&lt;/span&gt; &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;&amp;#39;555-7765123&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    t1&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Kind&lt;/span&gt; &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;&amp;#39;Casa&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    p&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Phones&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;t1&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Save&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;p&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt; &lt;span&gt;// save Person and Phones&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    guid &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; p&lt;span&gt;.&lt;/span&gt;&lt;span&gt;guid&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;finally&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Commit&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StartTransaction&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  p &lt;span&gt;:&lt;/span&gt;&lt;span&gt;=&lt;/span&gt; Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Load&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TypeInfo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;TPerson&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; guid&lt;span&gt;)&lt;/span&gt; &lt;span&gt;as&lt;/span&gt; TPerson&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;try&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    CheckEquals&lt;span&gt;(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; p&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Phones&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Count&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;finally&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    Session&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Commit&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;p&gt;Mapping, contained in a file called “dorm.conf”, is similar to the following:&lt;/p&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;&amp;quot;persistence&amp;quot;&lt;/span&gt;: &lt;span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;&amp;quot;database_adapter&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;dorm.adapter.Firebird.TFirebirdPersistStrategy&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;&amp;quot;database_connection_string&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;127.0.0.1:C:&lt;span&gt;\\&lt;/span&gt;MyProjects&lt;span&gt;\\&lt;/span&gt;DORM&lt;span&gt;\\&lt;/span&gt;experiments&lt;span&gt;\\&lt;/span&gt;dorm.fdb&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;&amp;quot;username&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;sysdba&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;&amp;quot;password&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;masterkey&amp;quot;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;&amp;quot;config&amp;quot;&lt;/span&gt;: &lt;span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;&amp;quot;package&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;dorm.bo.Person&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;&amp;quot;logger_class_name&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;dorm.loggers.FileLog.TdormFileLog&amp;quot;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;}&lt;/span&gt;,      &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;  &lt;span&gt;&amp;quot;mapping&amp;quot;&lt;/span&gt;:&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;{&lt;/span&gt;      &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;      &lt;span&gt;&amp;quot;TPerson&amp;quot;&lt;/span&gt;:&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;      &lt;span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;&amp;quot;table&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;people&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;&amp;quot;id&amp;quot;&lt;/span&gt;: &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;guid&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;guid&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;string&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;size&amp;quot;&lt;/span&gt;: &lt;span&gt;100&lt;/span&gt;, &lt;span&gt;&amp;quot;default_value&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;&amp;quot;fields&amp;quot;&lt;/span&gt;:&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;firstname&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;first_name&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;string&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;size&amp;quot;&lt;/span&gt;: &lt;span&gt;100&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;lastname&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;string&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;size&amp;quot;&lt;/span&gt;: &lt;span&gt;100&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;age&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;age&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;integer&amp;quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;borndate&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;born_date&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;date&amp;quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;]&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;&amp;quot;has_many&amp;quot;&lt;/span&gt;:&lt;span&gt;[&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;Phones&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;&amp;quot;class_name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;TPhone&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;&amp;quot;child_field_name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;guid_person&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;&amp;quot;lazy_load&amp;quot;&lt;/span&gt;: &lt;span&gt;false&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;}&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;&amp;quot;has_one&amp;quot;&lt;/span&gt;: &lt;span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;car&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;&amp;quot;class_name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;TCar&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;&amp;quot;child_field_name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;guid_person&amp;quot;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;      &lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;      &lt;span&gt;&amp;quot;TPhone&amp;quot;&lt;/span&gt;:&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;      &lt;span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;&amp;quot;table&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;phones&amp;quot;&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;&amp;quot;id&amp;quot;&lt;/span&gt;: &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;guid&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;guid&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;string&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;size&amp;quot;&lt;/span&gt;: &lt;span&gt;100&lt;/span&gt;, &lt;span&gt;&amp;quot;default_value&amp;quot;&lt;/span&gt;: &lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;        &lt;span&gt;&amp;quot;fields&amp;quot;&lt;/span&gt;:&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;number&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;number&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;string&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;size&amp;quot;&lt;/span&gt;: &lt;span&gt;100&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;string&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;size&amp;quot;&lt;/span&gt;: &lt;span&gt;100&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;,&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;guid_person&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;guid_person&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;field_type&amp;quot;&lt;/span&gt;:&lt;span&gt;&amp;quot;string&amp;quot;&lt;/span&gt;, &lt;span&gt;&amp;quot;size&amp;quot;&lt;/span&gt;: &lt;span&gt;100&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;          &lt;span&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;      &lt;span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;    &lt;span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;p&gt;The PODO (Plain Old Delphi Objects) can be binded to the VCL controls with a set of MediatingView (Model-GUI-Mediator Pattern) with an Observer mechanism to mantain things in synch.&lt;/p&gt;
&lt;p&gt;Any comments? Someone interested?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/alZF0gVOdnU" height="1" width="1"/&gt;</content><author><name>Daniele Teti</name></author><source gr:stream-id="feed/http://www.danieleteti.it/?feed=rss2"><id>tag:google.com,2005:reader/feed/http://www.danieleteti.it/?feed=rss2</id><title type="html">while true do;</title><link rel="alternate" href="http://www.danieleteti.it" type="text/html" /></source><feedburner:origLink>http://www.danieleteti.it/?p=250</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1283200445862"><id gr:original-id="http://delphi.about.com/b/2010/08/30/vigenere-cipher-algorithm-delphi-implementation-comments-by-alan-lloyd.htm">tag:google.com,2005:reader/item/3a5a060f755c5279</id><title type="html">Vigenere Cipher Algorithm - Delphi Implementation (Comments by Alan Lloyd)</title><published>2010-08-30T09:36:28Z</published><updated>2010-08-30T09:36:28Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/L2Zr1carOzg/vigenere-cipher-algorithm-delphi-implementation-comments-by-alan-lloyd.htm" type="text/html" /><summary xml:base="http://delphi.about.com/" type="html">in &lt;a href="http://delphi.about.com/b/2010/08/24/vigenere-cipher-delphi-implementation-fancy-delphi-application-contest-entry-49.htm"&gt;&lt;i&gt;Vigenere Cipher&lt;/i&gt;&lt;/a&gt; :: A long time Delphi  developer, Alan Lloyd had a few comments on the recently published &lt;a href="http://clk.about.com/?zi=1/1hc&amp;amp;zu=/b/2010/08/24/vigenere-cipher-delphi-implementation-fancy-delphi-application-contest-entry-49.htm"&gt;Vigenere Cipher - Delphi Implementation - Fancy Delphi Application Contest Entry #49&lt;/a&gt;.

&lt;p&gt;Alan suggests:

&lt;p&gt;While we have loads of computation power &amp;amp; memory available today, I think as a professional it is better to code quicker than slower, unless it makes code unclear.
 
&lt;p&gt;In the posted Vigenere code . . .
 
&lt;ol&gt;
&lt;li&gt;String memory allocation/re-allocation is slow so avoid ConCat(), String + String (even though its quicker than ConCat), and Delete(). Better to SetLength for strings and use index accessing for characters.&lt;/li&gt;
&lt;li&gt;Use 'for' loops rather than 'while' loops.&lt;/li&gt;
&lt;li&gt;Reduce the code for every character. Check for bEncrypt before entering repeated similar code in a 'for' loop for each character action.&lt;/li&gt;
&lt;li&gt;IMO sTable should be initialised before use by := '' or SetLength(). AIUI variables in functions are not zeroed, and you might be using garbage.&lt;/li&gt;
&lt;li&gt;Crypt by re-referencing the key as given rather that using multiple keys up to the source length.&lt;/li&gt;
&lt;/ol&gt;

Here's the Vigenere crypto algorithm as suggested by Allan:
&lt;pre&gt;&lt;code&gt;
&lt;b&gt;function&lt;/b&gt; Vigenere(Src, Key : &lt;b&gt;string&lt;/b&gt;; Encrypt : boolean) : &lt;b&gt;string&lt;/b&gt;;
const
  OrdMinChar : integer = Ord('A');
  OrdMaxChar : integer = Ord('Z');
  IncludeChars : set of char = ['A'..'Z'];
&lt;b&gt;var&lt;/b&gt;
  CharRangeCount, i, j, KeyLen, KeyInc, SrcOrd, CryptOrd : integer;
  SrcA : string;
&lt;b&gt;begin&lt;/b&gt;
  CharRangeCount := OrdMaxChar - OrdMinChar + 1;
  KeyLen := Length(Key);
  SetLength(SrcA, Length(Src));
  &lt;b&gt;If&lt;/b&gt; Encrypt &lt;b&gt;then&lt;/b&gt; 
  &lt;b&gt;begin&lt;/b&gt;
    &lt;i&gt;// transfer only included characters to SrcA for encryption&lt;/i&gt;
    j := 1;
    &lt;b&gt;for&lt;/b&gt; i := 1 &lt;b&gt;to&lt;/b&gt; Length(Src) &lt;b&gt;do&lt;/b&gt;
      &lt;b&gt;begin&lt;/b&gt;
      &lt;b&gt;if&lt;/b&gt; (Src[i] &lt;b&gt;in&lt;/b&gt; IncludeChars) &lt;b&gt;then&lt;/b&gt; 
      &lt;b&gt;begin&lt;/b&gt;
        SrcA[j] := Src[i];
        inc(j);
      &lt;b&gt;end&lt;/b&gt;;
    &lt;b&gt;end&lt;/b&gt;;
    SetLength(SrcA, j - 1);
  &lt;b&gt;end&lt;/b&gt;;
  SetLength(Result, Length(SrcA));
  &lt;b&gt;if&lt;/b&gt; Encrypt &lt;b&gt;then&lt;/b&gt;
    &lt;b&gt;begin&lt;/b&gt;
    &lt;i&gt;// Encrypt to Result&lt;/i&gt;
    &lt;b&gt;for&lt;/b&gt; i := 1 &lt;b&gt;to&lt;/b&gt; Length(SrcA) &lt;b&gt;do&lt;/b&gt; 
    &lt;b&gt;begin&lt;/b&gt;
      SrcOrd := Ord(Src[i]) - OrdMinChar;
      KeyInc := Ord(Key[((i - 1 ) &lt;b&gt;mod&lt;/b&gt; KeyLen)+ 1]) - OrdMinChar;
      CryptOrd := ((SrcOrd + KeyInc) &lt;b&gt;mod&lt;/b&gt; CharRangeCount) + OrdMinChar;
      Result[i] := Char(CryptOrd);
    &lt;b&gt;end&lt;/b&gt;;
  &lt;b&gt;end&lt;/b&gt;;
  &lt;b&gt;else&lt;/b&gt;
  &lt;b&gt;begin&lt;/b&gt;
    &lt;i&gt;// Decrypt to Result&lt;/i&gt;
    &lt;b&gt;for&lt;/b&gt; i := 1 &lt;b&gt;to&lt;/b&gt; Length(SrcA) &lt;b&gt;do&lt;/b&gt; 
    &lt;b&gt;begin&lt;/b&gt;
      SrcOrd := Ord(Src[i]) - OrdMinChar;
      KeyInc := Ord(Key[((i - 1 ) &lt;b&gt;mod&lt;/b&gt; KeyLen)+ 1]) - OrdMinChar;
      CryptOrd := ((SrcOrd - KeyInc + CharRangeCount) &lt;b&gt;mod&lt;/b&gt; CharRangeCount) + OrdMinChar;
      &lt;i&gt;// KeyInc may be larger than SrcOrd&lt;/i&gt;
      Result[i] := Char(CryptOrd);
    &lt;b&gt;end&lt;/b&gt;;
  &lt;b&gt;end&lt;/b&gt;;
&lt;b&gt;end&lt;/b&gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p style="background:#f5f3ef;border:1px solid #d5d0bf;clear:both;padding:.5em"&gt;&lt;a href="http://clk.about.com/?zi=1/1hc&amp;amp;zu=http://delphi.about.com/b/2010/08/30/vigenere-cipher-algorithm-delphi-implementation-comments-by-alan-lloyd.htm"&gt;Vigenere Cipher Algorithm - Delphi Implementation (Comments by Alan Lloyd)&lt;/a&gt; originally appeared on &lt;a href="http://clk.about.com/?zi=1/1hc&amp;amp;zu=http://delphi.about.com/"&gt;About.com Delphi Programming&lt;/a&gt; on Monday, August 30th, 2010 at 09:36:28.&lt;/p&gt;&lt;p&gt;&lt;a href="http://clk.about.com/?zi=1/1hc&amp;amp;zu=http://delphi.about.com/b/2010/08/30/vigenere-cipher-algorithm-delphi-implementation-comments-by-alan-lloyd.htm"&gt;Permalink&lt;/a&gt; | &lt;a href="http://clk.about.com/?zi=1/1hc&amp;amp;zu=http://delphi.about.com/b/2010/08/30/vigenere-cipher-algorithm-delphi-implementation-comments-by-alan-lloyd.htm#gB3"&gt;Comment&lt;/a&gt; | &lt;a href="http://delphi.about.com/gi/pages/shareurl.htm?PG=http://delphi.about.com/b/2010/08/30/vigenere-cipher-algorithm-delphi-implementation-comments-by-alan-lloyd.htm&amp;amp;zItl=Vigenere%20Cipher%20Algorithm%20-%20Delphi%20Implementation%20(Comments%20by%20Alan%20Lloyd)"&gt;Email this&lt;/a&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/L2Zr1carOzg" height="1" width="1"/&gt;</summary><author gr:unknown-author="true"><name>(author unknown)</name></author><source gr:stream-id="feed/http://z.about.com/6/g/delphi/b/index.xml"><id>tag:google.com,2005:reader/feed/http://z.about.com/6/g/delphi/b/index.xml</id><title type="html">About Delphi Programming</title><link rel="alternate" href="http://delphi.about.com/" type="text/html" /></source><feedburner:origLink>http://delphi.about.com/b/2010/08/30/vigenere-cipher-algorithm-delphi-implementation-comments-by-alan-lloyd.htm</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1282301900224"><id gr:original-id="http://blog.marcocantu.com/blog/delphi_xe_beta_rtl.html">tag:google.com,2005:reader/item/9bbfe20575b1ba19</id><title type="html">Delphi XE Beta Blogging: New in the RTL</title><published>2010-08-20T10:25:10Z</published><updated>2010-08-20T10:25:10Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/xIeC7Bi-z1s/delphi_xe_beta_rtl.html" type="text/html" /><content xml:base="http://blog.marcocantu.com/blog_rss2.xmldata" type="html">&lt;p&gt;In this third "beta blog" I'll just provide a (partial) list of new RTL classes and functions. I've picked just half a dozen of new things in the RTL I find very useful, but the complete list accounts for several dozens of significant changes.&lt;/p&gt;
    &lt;p style="margin-left:40px"&gt;
      &lt;em&gt;In case you don't know, "Delphi beta blogs" are authorized blog posts by independent bloggers covering features of a beta version of Delphi. This means I was given a specific permission to post about this topic and I'm discussing a feature of a pre-release version. Notice also that the official RAD Studio XE Preview page is at &lt;/em&gt; &lt;a style="text-decoration:none" href="http://www.embarcadero.com/rad-studio-xe-preview"&gt;
        &lt;em&gt;http://www.embarcadero.com/rad-studio-xe-preview&lt;/em&gt; &lt;/a&gt; &lt;em&gt;. Since this is a pre-release, there is no guarantee it will work the same in the final version (or will actually be in the product).&lt;/em&gt;
    &lt;/p&gt;
    &lt;p&gt;Here is a partial list of  new classes in Delphi XE RTL (compared to Delphi 2010):&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;TBinaryReader and TBinaryWriter somewhat counterparts of the TTextReader and TTextWriter introduced in Delphi 2009&lt;/li&gt;
      &lt;li&gt;TTimeZone is a little helper for managing time zone and computing time differences&lt;/li&gt;
      &lt;li&gt;TInterlocked, TSpinWait, TSpinLock and many other new core synchronization classes help you push your multi-threaded code further and make it more cross-platform (as these classes have a native implementation, based on only core OS support). The TThread class has been also extended with direct execution of anonymous methods inside a temporary thread and several other features.&lt;/li&gt;
      &lt;li&gt;TRegEx is the core record implementing native regular expressions support. This is a big step forward, despite many developers already used third party libraries for regular expressions.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;Other notable changes, beside new classes, include:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;The addition of a DefaultEncoding to TStrings, which lets you pick for Unicode format when a list of strings to a text file. There is also support for converting string lists to and from arrays of strings.&lt;/li&gt;
      &lt;li&gt;The TPath record in IOUtils has a new GetHomePath class method, which on Windows returns the applications data folder, “AppData\Roaming”). The method calls a corresponding new function in SysUtils. There are actually a lot of improvements in file management, for example with the inclusion on TSymLink, and abstraction... all due to the coming cross platform support.&lt;/li&gt;
      &lt;li&gt;Finally, I'd like to mention one of the new functions, SplitStrings. This is quite fast, compared with other techniques I used in the past for splitting strings. Another small nice addition.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;Again, this is a very partial and limited list of features, nothing revolutionary but many welcome additions.&lt;/p&gt;
  &lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/v44mj3svm5mco3spnk45jgkjqk/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fblog.marcocantu.com%2Fblog%2Fdelphi_xe_beta_rtl.html" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/marcocantublog/~4/ucAZcWNKhhk" height="1" width="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/xIeC7Bi-z1s" height="1" width="1"/&gt;</content><author><name>marcocantu</name></author><source gr:stream-id="feed/http://blog.marcocantu.com/blog_rss2.xmldata"><id>tag:google.com,2005:reader/feed/http://blog.marcocantu.com/blog_rss2.xmldata</id><title type="html">marcocantu.blog</title><link rel="alternate" href="http://blog.marcocantu.com/blog_rss2.xmldata" type="text/html" /></source><feedburner:origLink>http://feedproxy.google.com/~r/marcocantublog/~3/ucAZcWNKhhk/delphi_xe_beta_rtl.html</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1282297400067"><id gr:original-id="http://blogs.remobjects.com/?p=1780">tag:google.com,2005:reader/item/4262d1272b887dca</id><category term=".NET" /><category term="Android" /><category term="Delphi Prism" /><category term="Mono" /><category term="MonoDroid" /><category term="Oxygene" /><category term="Platforms" /><category term="Visual Studio" /><title type="html">Teaser – MonoDroid with Oxygene</title><published>2010-08-19T22:02:47Z</published><updated>2010-08-19T22:02:47Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/BE8HYs5hngc/p1780" type="text/html" /><content xml:base="http://blogs.remobjects.com/" type="html">&lt;p&gt;Now that the &lt;a href="http://monodroid.net"&gt;MonoDroid&lt;/a&gt; preview is out, I thought I’d experiment a little with Oxygene (aka &lt;a href="http://www.embarcadero.com/products/delphi-prism"&gt;Delphi Prism&lt;/a&gt;), so I ported the “Button” sample to Oxygene. Here’s a taste of what I came up with:&lt;/p&gt;
&lt;p style="text-align:center"&gt;&lt;img title="Hello from Oxygene" src="http://rorox.remobjects.com/2010-08-19_1050.png" alt="" width="555" height="396"&gt;&lt;/p&gt;

&lt;div&gt;&lt;div&gt;&lt;pre style="font-family:monospace"&gt;&lt;span style="color:#000000;font-weight:bold"&gt;method&lt;/span&gt; Activity1&lt;span style="color:#000066"&gt;.&lt;/span&gt;&lt;span style="color:#000000"&gt;OnCreate&lt;/span&gt;&lt;span style="color:#000066"&gt;(&lt;/span&gt;bundle &lt;span style="color:#000066"&gt;:&lt;/span&gt; Bundle&lt;span style="color:#000066"&gt;)&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;
&lt;span style="color:#000000;font-weight:bold"&gt;begin&lt;/span&gt;
    &lt;span style="color:#000000;font-weight:bold"&gt;inherited&lt;/span&gt; OnCreate&lt;span style="color:#000066"&gt;(&lt;/span&gt;bundle&lt;span style="color:#000066"&gt;)&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;
 
    &lt;span style="color:#808080;font-style:italic"&gt;// Create your application here&lt;/span&gt;
    &lt;span style="color:#000000;font-weight:bold"&gt;var&lt;/span&gt; button &lt;span style="color:#000066"&gt;:&lt;/span&gt;&lt;span style="color:#000066"&gt;=&lt;/span&gt; &lt;span style="color:#000000;font-weight:bold"&gt;new&lt;/span&gt; Button&lt;span style="color:#000066"&gt;(&lt;/span&gt;&lt;span style="color:#000000;font-weight:bold"&gt;self&lt;/span&gt;&lt;span style="color:#000066"&gt;)&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;
 
    button&lt;span style="color:#000066"&gt;.&lt;/span&gt;&lt;span style="color:#000000"&gt;Text&lt;/span&gt; &lt;span style="color:#000066"&gt;:&lt;/span&gt;&lt;span style="color:#000066"&gt;=&lt;/span&gt; &lt;span style="color:#ff0000"&gt;'Oxygene Says: Click Me!'&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;
    button&lt;span style="color:#000066"&gt;.&lt;/span&gt;&lt;span style="color:#000000"&gt;Click&lt;/span&gt; &lt;span style="color:#000066"&gt;+=&lt;/span&gt; &lt;span style="color:#000000;font-weight:bold"&gt;method&lt;/span&gt; &lt;span style="color:#000000;font-weight:bold"&gt;begin&lt;/span&gt;
      button&lt;span style="color:#000066"&gt;.&lt;/span&gt;&lt;span style="color:#000000"&gt;Text&lt;/span&gt; &lt;span style="color:#000066"&gt;:&lt;/span&gt;&lt;span style="color:#000066"&gt;=&lt;/span&gt; string&lt;span style="color:#000066"&gt;.&lt;/span&gt;&lt;span style="color:#000000"&gt;Format&lt;/span&gt;&lt;span style="color:#000066"&gt;(&lt;/span&gt;&lt;span style="color:#ff0000"&gt;'{0} clicks!'&lt;/span&gt;&lt;span style="color:#000066"&gt;,&lt;/span&gt; count&lt;span style="color:#000066"&gt;)&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;
      &lt;span style="color:#000066"&gt;inc&lt;/span&gt;&lt;span style="color:#000066"&gt;(&lt;/span&gt;count&lt;span style="color:#000066"&gt;)&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;
    &lt;span style="color:#000000;font-weight:bold"&gt;end&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;
 
    SetContentView&lt;span style="color:#000066"&gt;(&lt;/span&gt;button&lt;span style="color:#000066"&gt;)&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;
&lt;span style="color:#000000;font-weight:bold"&gt;end&lt;/span&gt;&lt;span style="color:#000066"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, there’s not a lot of difference from the C# version.&lt;/p&gt;
&lt;p&gt;Obviously, this won’t be in the build that we RTM’ed last week, and will soon be available from our friends at Embarcadero, but it will work with said release. So if you’re a Delphi Prism customer, or just have a fondness for Pascal  syntax, keep an eye out here – more info will be available soon,  including templates &amp;amp; other support files.&lt;/p&gt;
&lt;div style="width:1px;height:1px;overflow:hidden"&gt;method Activity1.OnCreate(bundle : Bundle);&lt;br&gt;
begin&lt;br&gt;
inherited OnCreate(bundle);
&lt;p&gt;// Create your application here&lt;br&gt;
var button := new Button(self);&lt;/p&gt;
&lt;p&gt;button.Text := ‘Oxygene Says: Click Me!’;&lt;br&gt;
button.Click += method begin&lt;br&gt;
button.Text := string.Format (‘{0} clicks!’, count);&lt;br&gt;
inc(count);&lt;br&gt;
end;&lt;/p&gt;
&lt;p&gt;SetContentView (button);&lt;br&gt;
end;&lt;/p&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/BE8HYs5hngc" height="1" width="1"/&gt;</content><author><name>R. Brian Lindahl</name></author><source gr:stream-id="feed/http://blogs.remobjects.com/blogs/xmlsrv/rss2.php?blog=1"><id>tag:google.com,2005:reader/feed/http://blogs.remobjects.com/blogs/xmlsrv/rss2.php?blog=1</id><title type="html">RemObjects Blogs</title><link rel="alternate" href="http://blogs.remobjects.com" type="text/html" /></source><feedburner:origLink>http://blogs.remobjects.com/blogs/bl/2010/08/20/p1780</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1282074422241"><id gr:original-id="http://www.uweraabe.de/Blog/?p=105">tag:google.com,2005:reader/item/16890a50d0451be3</id><category term="Delphi" /><category term="Programming" /><title type="html">The Visitor Pattern – Part 4</title><published>2010-08-17T13:17:43Z</published><updated>2010-08-17T13:17:43Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/2V47tAED3SE/" type="text/html" /><content xml:base="http://www.uweraabe.de/Blog" type="html">&lt;p&gt;The interface approach introduced in Part 2 of this series and extended in Part 3 did cover most of our needs. But there is nothing that can’t be done better with the right tools.&lt;br&gt;
&lt;span&gt;&lt;/span&gt;&lt;br&gt;
I’ve been using this approach for a couple of years and it made my life a lot easier. You need an export as DXF? No problem! Displaying in OpenGL? I’ll write a new visitor!&lt;/p&gt;
&lt;p&gt;Writing the additional interfaces was easy done with the help of a customized code template, so that has never been a pain. The only thing that bothered me over time was that I could only apply the Visitor Pattern to classes I have control of. I just wasn’t able to visit, say, all the components of a TForm in a descent fashion (i.e. not queueing &lt;em&gt;if component is something then &amp;lt;typecast&amp;gt;&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;While digging through the new features of Delphi 2010 I discovered a solution which is as clean, lean, flexible and elegant as it could be. A little RTTI and some decent naming convention did the trick. Here is the code:&lt;/p&gt;
&lt;pre&gt;unit uVisitor;

interface

type
  TVisitor = class
  public
    procedure Visit(Instance: TObject); virtual;
  end;

implementation

uses
  Rtti;

procedure TVisitor.Visit(Instance: TObject);
var
  context: TRttiContext;
  currentClass: TClass;
  params: TArray
;
  paramType: TRttiType;
  selfMethod: TRttiMethod;
  S: string;
begin
  context := TRttiContext.Create;
  currentClass := Instance.ClassType;
  repeat
    S := currentClass.ClassName;
    Delete(S, 1, 1); // remove "T"
    for selfMethod in context.GetType(self.ClassType).GetMethods('Visit' + S) do begin
      params := selfMethod.GetParameters;
      if (Length(params) = 1) then begin
        paramType := params[0].ParamType;
        if ParamType.IsInstance and (ParamType.AsInstance.MetaclassType = currentClass)then begin
          selfMethod.Invoke(Self, [Instance]);
          Exit;
        end;
      end;
    end;
    currentClass := currentClass.ClassParent;
  until currentClass = nil;
end;

end.
&lt;/pre&gt;
&lt;p&gt;And here is a visitor capable of handling some VCL controls on a form together with an example of its usage:&lt;/p&gt;
&lt;pre&gt;type
  TMyVisitor = class(TVisitor)
  public
    procedure VisitButton(Instance: TButton);
    procedure VisitLabel(Instance: TLabel);
    procedure VisitEdit(Instance: TEdit);
    procedure VisitMemo(Instance: TMemo);
  end;

procedure TMyVisitor.VisitButton(Instance: TButton);
begin
  Instance.Caption := 'a button';
end;

procedure TMyVisitor.VisitEdit(Instance: TEdit);
begin
  Instance.Text := 'an edit';
end;

procedure TMyVisitor.VisitLabel(Instance: TLabel);
begin
  Instance.Caption := 'a label';
end;

procedure TMyVisitor.VisitMemo(Instance: TMemo);
begin
  Instance.Lines.Clear;
  Instance.Lines.Add('a memo');
end;

procedure TForm40.Button1Click(Sender: TObject);
var
  I: Integer;
  visitor: TMyVisitor;
begin
  visitor := TMyVisitor.Create;
  try
    for I := 0 to ComponentCount - 1 do
      visitor.Visit(Components[I]);
  finally
    visitor.Free;
  end;
end;
&lt;/pre&gt;
&lt;p&gt;If you need to visit some class, just introduce a new method with a suitable name and signature and you are done. No new interfaces, no fiddling around with classes. It just works right out of the box.&lt;/p&gt;
&lt;p&gt;I’m still visualizing some possible scenarios where this approach can be useful, too. Stay tuned.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/2V47tAED3SE" height="1" width="1"/&gt;</content><author><name>Uwe Raabe</name></author><source gr:stream-id="feed/http://www.uweraabe.de/Blog/feed/"><id>tag:google.com,2005:reader/feed/http://www.uweraabe.de/Blog/feed/</id><title type="html">The Art of Delphi Programming</title><link rel="alternate" href="http://www.uweraabe.de/Blog" type="text/html" /></source><feedburner:origLink>http://www.uweraabe.de/Blog/2010/08/17/the-visitor-pattern-part-4/</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1282074421875"><id gr:original-id="http://www.uweraabe.de/Blog/?p=103">tag:google.com,2005:reader/item/53ed8d0289c9e611</id><category term="Delphi" /><category term="Programming" /><title type="html">The Visitor Pattern – Part 3</title><published>2010-08-17T08:13:37Z</published><updated>2010-08-17T08:13:37Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/kL10sK3VMQs/" type="text/html" /><content xml:base="http://www.uweraabe.de/Blog" type="html">&lt;p&gt;In Part 2 of this series we learned about a more flexible implementation of the Visitor Pattern than the traditional approach. But we can do better.&lt;br&gt;
&lt;span&gt;&lt;/span&gt;&lt;br&gt;
When we have a usual class inheritance within our shape or whatever classes, it might be desirable to handle groups of classes with a common ancestor all the same. For now we have to implement each interface individually. A slight change does the trick. We introduce a visitor interface for TAbstractShape, make TAbstractShape.Accept not abstract. Then we change the Accept implementations of the derived shapes to first check the visitor implementing the interface and call inherited otherwise.&lt;/p&gt;
&lt;pre&gt;unit uShapeBase;

interface

uses
  Classes, SysUtils;

type
  ENotSupported = class(Exception);

type
  TAbstractShape = class
  public
    procedure Accept(Visitor: IInterface); virtual;
  end;

  IAbstractShapeVisitor = interface
    ['{7ED85A22-564A-4F23-AF32-37D29FD3C623}']
    procedure VisitAbstractShape(Instance: TAbstractShape);
  end;

  { we avoid ref-counting here }
  TShapeVisitor = class(TInterfacedPersistent)
  public
    procedure Visit(Instance: TAbstractShape);
  end;

type
  TShapeRectangle = class(TAbstractShape)
  private
    FX0: Double;
    FX1: Double;
    FY0: Double;
    FY1: Double;
  public
    procedure Accept(Visitor: IInterface); override;
    property X0: Double read FX0 write FX0;
    property X1: Double read FX1 write FX1;
    property Y0: Double read FY0 write FY0;
    property Y1: Double read FY1 write FY1;
  end;

  IShapeRectangleVisitor = interface
    ['{6F521E71-5DB8-4ECE-B453-60F9A3B8BE22}']
    procedure VisitShapeRectangle(Instance: TShapeRectangle);
  end;

type
  TShapeCircle = class(TAbstractShape)
  private
    FCenterX: Double;
    FCenterY: Double;
    FRadius: Double;
  public
    procedure Accept(Visitor: IInterface); override;
    property CenterX: Double read FCenterX write FCenterX;
    property CenterY: Double read FCenterY write FCenterY;
    property Radius: Double read FRadius write FRadius;
  end;

  IShapeCircleVisitor = interface
    ['{27D7DCD3-952A-4879-8667-E86023612BFB}']
    procedure VisitShapeCircle(Instance: TShapeCircle);
  end;

implementation

procedure TShapeVisitor.Visit(Instance: TAbstractShape);
begin
  Instance.Accept(Self);
end;

procedure TShapeCircle.Accept(Visitor: TShapeVisitor);
var
  myVisitor: IShapeCircleVisitor;
begin
  if Supports(Visitor, IShapeCircleVisitor, myVisitor) then
    myVisitor.VisitShapeCircle(Self)
  else
    inherited;
end;

procedure TShapeRectangle.Accept(Visitor: IInterface);
var
  myVisitor: IShapeRectangleVisitor;
begin
  if Supports(Visitor, IShapeRectangleVisitor, myVisitor) then
    myVisitor.VisitShapeRectangle(Self)
  else
    inherited;
end;

procedure TAbstractShape.Accept(Visitor: IInterface);
var
  myVisitor: IAbstractShapeVisitor;
begin
  if Supports(Visitor, IAbstractShapeVisitor, myVisitor) then
    myVisitor.VisitAbstractShape(Self)
  else
    raise ENotSupported.Create('Visitor doesn''t support ' + ClassName);
end;

end.&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/kL10sK3VMQs" height="1" width="1"/&gt;</content><author><name>Uwe Raabe</name></author><source gr:stream-id="feed/http://www.uweraabe.de/Blog/feed/"><id>tag:google.com,2005:reader/feed/http://www.uweraabe.de/Blog/feed/</id><title type="html">The Art of Delphi Programming</title><link rel="alternate" href="http://www.uweraabe.de/Blog" type="text/html" /></source><feedburner:origLink>http://www.uweraabe.de/Blog/2010/08/17/the-visitor-pattern-part-3/</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1282074420862"><id gr:original-id="http://www.uweraabe.de/Blog/?p=101">tag:google.com,2005:reader/item/46a422b454f61a69</id><category term="Delphi" /><category term="Programming" /><title type="html">The Visitor Pattern – Part 2</title><published>2010-08-16T21:33:28Z</published><updated>2010-08-16T21:33:28Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/f8JkuKHVo1Q/" type="text/html" /><content xml:base="http://www.uweraabe.de/Blog" type="html">&lt;p&gt;In Part 1 of this series we learned about the benefits of the Visitor Pattern and saw a basic approach according to the GoF description.&lt;/p&gt;
&lt;p&gt;As clean and elegant the visitor pattern might look in the first place, it nonetheless has its disadvantages. Say, we want to add a new shape TShapeTriangle. We have to do it inside the same unit the other shapes are declared. As the shapes reference the visitor and the visitor references the shapes we have to put all shape classes together with the visitor into the same unit. Although this might work in some smaller scenarios, it definitely doesn’t in most of the real ones. Probably this is one of the reasons why the Visitor Pattern is not as famous as it should be.&lt;/p&gt;
&lt;p&gt;Can we find a solution? Yes, we can!&lt;br&gt;
&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Lets examine why there is such a close coupling between all the shapes and the visitor: The shapes use the visitor’s method corresponding to their own class and the visitor has to know about all the shapes it has to handle. How can we break this up?&lt;/p&gt;
&lt;p&gt;The answer are &lt;strong&gt;interfaces&lt;/strong&gt;! Instead of declaring a visitor capable of handling every defined shape, we declare an interface for each shape that only handles that specific shape.&lt;/p&gt;
&lt;pre&gt;unit uShapeBase;

interface

uses
  Classes;

type
  TAbstractShape = class
  public
    procedure Accept(Visitor: IInterface); virtual; abstract;
  end;

  { we avoid ref-counting here }
  TShapeVisitor = class(TInterfacedPersistent)
  public
    procedure Visit(Instance: TAbstractShape);
  end;

type
  TShapeRectangle = class(TAbstractShape)
  private
    FX0: Double;
    FX1: Double;
    FY0: Double;
    FY1: Double;
  public
    procedure Accept(Visitor: IInterface); override;
    property X0: Double read FX0 write FX0;
    property X1: Double read FX1 write FX1;
    property Y0: Double read FY0 write FY0;
    property Y1: Double read FY1 write FY1;
  end;

  IShapeRectangleVisitor = interface
    ['{6F521E71-5DB8-4ECE-B453-60F9A3B8BE22}']
    procedure VisitShapeRectangle(Instance: TShapeRectangle);
  end;

type
  TShapeCircle = class(TAbstractShape)
  private
    FCenterX: Double;
    FCenterY: Double;
    FRadius: Double;
  public
    procedure Accept(Visitor: IInterface); override;
    property CenterX: Double read FCenterX write FCenterX;
    property CenterY: Double read FCenterY write FCenterY;
    property Radius: Double read FRadius write FRadius;
  end;

  IShapeCircleVisitor = interface
    ['{27D7DCD3-952A-4879-8667-E86023612BFB}']
    procedure VisitShapeCircle(Instance: TShapeCircle);
  end;

implementation

uses
  SysUtils;

procedure TShapeVisitor.Visit(Instance: TAbstractShape);
begin
  Instance.Accept(Self);
end;

procedure TShapeCircle.Accept(Visitor: TShapeVisitor);
begin
  (Visitor as IShapeCircleVisitor).VisitShapeCircle(Self);
end;

procedure TShapeRectangle.Accept(Visitor: TShapeVisitor);
begin
  (Visitor as IShapeRectangleVisitor).VisitShapeRectangle(Self);
end;

end.
&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/f8JkuKHVo1Q" height="1" width="1"/&gt;</content><author><name>Uwe Raabe</name></author><source gr:stream-id="feed/http://www.uweraabe.de/Blog/feed/"><id>tag:google.com,2005:reader/feed/http://www.uweraabe.de/Blog/feed/</id><title type="html">The Art of Delphi Programming</title><link rel="alternate" href="http://www.uweraabe.de/Blog" type="text/html" /></source><feedburner:origLink>http://www.uweraabe.de/Blog/2010/08/16/the-visitor-pattern-part-2/</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1282074419428"><id gr:original-id="http://www.uweraabe.de/Blog/?p=99">tag:google.com,2005:reader/item/3d7a231b6ff6b109</id><category term="Delphi" /><category term="Programming" /><title type="html">The Visitor Pattern – Part 1</title><published>2010-08-16T14:12:01Z</published><updated>2010-08-16T14:12:01Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/Y3JOKYY6x9w/" type="text/html" /><content xml:base="http://www.uweraabe.de/Blog" type="html">&lt;p&gt;Some of you might have already heard of the Visitor Pattern, especially if you have read the GoF book &lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612"&gt;&lt;em&gt;Design Patterns&lt;/em&gt;&lt;/a&gt;, but do you really use it? Do you use it often?&lt;/p&gt;
&lt;p&gt;The common answer to this question is &lt;em&gt;No&lt;/em&gt;. Once I was even confrontated with the question &lt;em&gt;“Does anybody use it in real code at all?”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Well, I do – and here I’m going to explain the &lt;em&gt;why&lt;/em&gt; and the &lt;em&gt;how&lt;/em&gt;. Actually there are different &lt;em&gt;hows&lt;/em&gt; and at the end I will introduce a real elegant &lt;em&gt;how&lt;/em&gt;…&lt;br&gt;
&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Some basics: the Visitor Pattern is used to decouple an operation from the class it operates on and thus allows to create new operations without changing the class.&lt;/p&gt;
&lt;p&gt;Let me give you an example: Assume we have a shape class providing the necessary properties to define the shape completely. To draw the shape onto a TCanvas we can introduce a Draw method with a Canvas as parameter. Easy done and easily extended to other shapes. We normally would introduce a TAbstractShape with an abstract Draw method ond override this in the derived classes.&lt;/p&gt;
&lt;p&gt;Next task will be to store the shapes somehow into an inifile and read it back. The classical approach would be to introduce two methods LoadFromFile and SaveToFile each with a TCustomInifile parameter probably accompanied by a section name. I’m sure we’ve all done that before.&lt;/p&gt;
&lt;p&gt;Requirements change: the drawing should be done with OpenGL and instead of inifiles we use XML now – but the other behaviour has to remain for compatibility reasons. I know, there are OpenGL wrappers that emulate a TCanvas and so are XML wrappers emulating a TCustomInifile, but honestly – such an approach is just crap, isn’t it? We have to introduce some overloaded methods with an OpenGL context for drawing and an XMLDocument for reading and writing to get this done properly. Oh, I just heard someone mentioning Direct3D…&lt;/p&gt;
&lt;p&gt;We are actually following a pattern here: introduce an abstract method in the abstract ancestor and implement the specific behaviour in the derived classes. As a side effect we have to &lt;em&gt;use&lt;/em&gt; a bunch of units in the abstract class that normally wouldn’t belong there. This can be really awkward when you need the classes, but don’t use the additional functionality, like drawing to OpenGL or writing to XML. Although a perfect valid object-oriented approach, it doesn’t contribute to the modularity of the application.&lt;/p&gt;
&lt;p&gt;Here the Visitor Pattern steps in. Its goal is to move the operations from the class (in our case TAbstractShape and descendants) to different visitor classes. So there will be one for drawing to a TCanvas, one for the OpenGL output, two classes for reading and writing inifiles and two for reading and writing XML files.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/Y3JOKYY6x9w" height="1" width="1"/&gt;</content><author><name>Uwe Raabe</name></author><source gr:stream-id="feed/http://www.uweraabe.de/Blog/feed/"><id>tag:google.com,2005:reader/feed/http://www.uweraabe.de/Blog/feed/</id><title type="html">The Art of Delphi Programming</title><link rel="alternate" href="http://www.uweraabe.de/Blog" type="text/html" /></source><feedburner:origLink>http://www.uweraabe.de/Blog/2010/08/16/the-visitor-pattern-part-1/</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1281302831413"><id gr:original-id="d21fbbc9-c112-4f32-ad14-95939a2c53d4:1067826">tag:google.com,2005:reader/item/798539ffb12ef5af</id><category term="Miscellaneous" scheme="http://codebetter.com/blogs/james.kovacs/archive/tags/Miscellaneous/default.aspx" /><category term="Hardware" scheme="http://codebetter.com/blogs/james.kovacs/archive/tags/Hardware/default.aspx" /><title type="html">Improving Your Audio: Hardware Edition</title><published>2010-08-07T18:22:00Z</published><updated>2010-08-07T18:22:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/ODhZZZgWVrY/improving-your-audio-hardware-edition.aspx" type="text/html" /><summary xml:base="http://codebetter.com/" type="html">&lt;p&gt;[ASIDE: Community Server (our current blogging engine here at CodeBetter.com) is swallowing the HTML5 &amp;lt;audio&amp;gt; tags in this post along with the Flash Player fallback. To hear HTML5 audio in your browser, jump to &lt;a href="http://jameskovacs.com/2010/08/07/improving-your-audio-hardware-edition/"&gt;here&lt;/a&gt; with a browser that supports HTML5 audio such as FireFox 3.5+, Chrome, Safari, Opera, or IE9. I&amp;#39;ve successfully tested it in FireFox 4.0b2 and Chrome 6. I&amp;#39;ve also successfully tested it in IE8 where it falls back to the Flash Player. Sorry for the hassle.]&lt;/p&gt;
&lt;p&gt;[ASIDE Part Deux: Brendan has tweaked the Community Server settings to allow CodeBetter to serve up &amp;lt;audio&amp;gt; tags. So the audio below should work now. Thanks, Brendan!]&lt;/p&gt;
&lt;p&gt;Over the years, I’ve done a lot of audio work between podcasts, screencasts, and webcasts. So I know a thing or two about computer audio. I don’t claim to be an expert like my friends &lt;a href="http://www.franklins.net"&gt;Carl Franklin&lt;/a&gt; or &lt;a href="http://www.campbellassociates.ca"&gt;Richard Campbell&lt;/a&gt;, but I’ve done enough to be able to offer some helpful tips. We’re going to start with the hardware.&lt;/p&gt;
&lt;p&gt;The quality of your computer audio can only be as good as the raw captured product. Use a bad microphone and no amount of software cleanup is going to magically produce good audio. You might be wondering how much difference the hardware can make? I’ve recorded the same audio track using four (4) different microphones on the same computer. (I didn’t record them simultaneously as multi-track recording is notoriously difficult, but I did say the same phrase into each microphone on after the other.) Let’s start with the LifeChat ZX-6000.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;margin-left:0px;border-left-width:0px;margin-right:0px" title="LifeChat ZX-6000" alt="LifeChat ZX-6000" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/james.kovacs/image_5F00_702A4488.png" border="0" height="112" width="154"&gt; &lt;audio controls&gt;&lt;source src="http://jameskovacs.com/wp-content/uploads/LifeChatZX-6000.ogg" type="audio/ogg"&gt;&lt;source src="http://jameskovacs.com/wp-content/uploads/LifeChatZX-6000.mp3" type="audio/mpeg"&gt;





  No audio playback capabilities, please download the audio below&lt;br&gt;&lt;b&gt;Download Audio:&lt;/b&gt; Closed Format: &lt;a href="http://jameskovacs.com/wp-content/uploads/LifeChatZX-6000.mp3"&gt;MP3&lt;/a&gt; Open Format: &lt;a href="http://jameskovacs.com/wp-content/uploads/LifeChatZX-6000.ogg"&gt;OGG&lt;/a&gt;  

&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;My voice sounds like I’m on a telephone. The sound is hollow and lacks depth. If we plot a frequency analysis using &lt;a href="http://audacity.sourceforge.net/"&gt;Audacity&lt;/a&gt;, we can easily see the problems.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="LifeChat ZX-6000 Frequency Spectrum" alt="LifeChat ZX-6000 Frequency Spectrum" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/james.kovacs/image_5F00_4F36D1E1.png" border="0" height="542" width="618"&gt; &lt;/p&gt;
&lt;p&gt;OK, maybe not easily if you’re not familiar with audio. Let me explain some basic ideas and then you should be able to see the problems.&lt;/p&gt;
&lt;p&gt;Normal human hearing discerns frequencies between 20 Hz and 20 kHz. The standard tuning note for musicians is the 440 Hz, which is an A above middle C on the piano. The lowest note on the piano (A0) is 27.5 Hz and the highest note (C8) is 4186 Hz. (I’m using the example of a piano since many people, even non-musicians, have at least played with a piano at one time or another.) Lower frequencies correspond to lower notes and higher frequencies to higher notes. The frequencies mentioned are the fundamental frequencies. When you play an A4 on the piano (or any other instrument including the human voice), the major frequency is 440 Hz, but there are many harmonics or overtones that occur. These harmonics give a colour and depth to the sound. This is one of the reasons why different instruments sound vastly different when playing the same note – the harmonics produced by each instrument are quite different. This is how we perceive different ranges of audio frequencies. (Taken from &lt;a href="http://en.wikipedia.org/wiki/Audio_frequency"&gt;Wikipedia Audio Frequency&lt;/a&gt;.)&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;     
&lt;tr&gt;
&lt;th&gt;Frequency (Hz)&lt;/th&gt;        &lt;th&gt;Octave&lt;/th&gt;        &lt;th&gt;Description&lt;/th&gt;     
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;16 to 32&lt;/td&gt;
&lt;td&gt;1st&lt;/td&gt;
&lt;td&gt;The human threshold of feeling, and the lowest pedal notes of a pipe organ.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32 to 512&lt;/td&gt;
&lt;td&gt;2nd to 5th&lt;/td&gt;
&lt;td&gt;Rhythm frequencies, where the lower and upper bass notes lie.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;512 to 2048&lt;/td&gt;
&lt;td&gt;6th to 7th&lt;/td&gt;
&lt;td&gt;Defines human speech intelligibility, gives a horn-like or tinny quality to sound.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2048 to 8192&lt;/td&gt;
&lt;td&gt;8th to 9th&lt;/td&gt;
&lt;td&gt;Gives presence to speech, where labial and fricative sounds lie.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8192 to 16384&lt;/td&gt;
&lt;td&gt;10th&lt;/td&gt;
&lt;td&gt;Brilliance, the sounds of bells and the ringing of cymbals. In speech, the sound of the letter &amp;quot;S&amp;quot; (8000-11000 Hz)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Note how 2048 to 8192 Hz gives a presence to speech, whereas 8192 to 16384 give a brilliance. Without these frequencies present, speech will sound hollow.&lt;/p&gt;
&lt;p&gt;With this in mind, let’s take another look at the frequency spectrum from the LifeChat ZX-6000. We see virtually no frequencies above 4000 Hz, which is making my voice sound hollow. Old analog telephones transmitted 200 Hz to 3000 Hz, which is why it sounds like I’m talking on an old phone. You’ll also note that the lower frequencies (below 400 Hz) are attenuated (e.g. not as pronounced), which is why the sound is lacking some of the bass timbre of my voice.&lt;/p&gt;
&lt;p&gt;Let’s try a different microphone and see how it performs… Next up the LifeChat LX-3000.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="LifeChat LX-3000" alt="LifeChat LX-3000" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/james.kovacs/lx3000_5F00_5FCECCCF.jpg" border="0" height="193" width="154"&gt; &lt;audio controls&gt;&lt;source src="http://jameskovacs.com/wp-content/uploads/LifeChatLX-3000.ogg" type="audio/ogg"&gt;&lt;source src="http://jameskovacs.com/wp-content/uploads/LifeChatLX-3000.mp3" type="audio/mpeg"&gt;





  No audio playback capabilities, please download the audio below&lt;br&gt;&lt;b&gt;Download Audio:&lt;/b&gt; Closed Format: &lt;a href="http://jameskovacs.com/wp-content/uploads/LifeChatLX-3000.mp3"&gt;MP3&lt;/a&gt; Open Format: &lt;a href="http://jameskovacs.com/wp-content/uploads/LifeChatLX-3000.ogg"&gt;OGG&lt;/a&gt;  

&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;The audio quality is vastly improved. Let’s take a look at the frequency spectrum.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="LifeChat LX-3000 Frequency Spectrum" alt="LifeChat LX-3000 Frequency Spectrum" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/james.kovacs/image_5F00_7F1173A2.png" border="0" height="546" width="622"&gt; &lt;/p&gt;
&lt;p&gt;You can visibly see the difference. We have frequency response all the way up to 20 kHz with the majority of the response in the lower frequencies, which is expected due to the timbre of my voice. The lower frequencies are also not as attenuated. The quality of the sound is much warmer and vibrant with the LX-3000 than the ZX-6000.&lt;/p&gt;
&lt;p&gt;As our last point of comparison, let’s listen to a semi-pro microphone – the one I use for my recording work – the audio-technica AT2020.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/james.kovacs/image_5F00_3D96C149.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="audio-technica AT2020" alt="audio-technica AT2020" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/james.kovacs/image_5F00_thumb_5F00_23565825.png" border="0" height="229" width="153"&gt;&lt;/a&gt; &lt;audio controls&gt;&lt;source src="http://jameskovacs.com/wp-content/uploads/AudioTechnica.ogg" type="audio/ogg"&gt;&lt;source src="http://jameskovacs.com/wp-content/uploads/AudioTechnica.mp3" type="audio/mpeg"&gt;





  No audio playback capabilities, please download the audio below&lt;br&gt;&lt;b&gt;Download Audio:&lt;/b&gt; Closed Format: &lt;a href="http://jameskovacs.com/wp-content/uploads/AudioTechnica.mp3"&gt;MP3&lt;/a&gt; Open Format: &lt;a href="http://jameskovacs.com/wp-content/uploads/AudioTechnica.ogg"&gt;OGG&lt;/a&gt;  

&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;The differences are subtler this time, but still noticeable. The audio has more depth and presence than with the LX-3000. Let’s take a look at the frequency spectrum.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="audio-technica AT2020 Frequency Spectrum" alt="audio-technica AT2020 Frequency Spectrum" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/james.kovacs/image_5F00_3B0D8F8B.png" border="0" height="542" width="618"&gt; &lt;/p&gt;
&lt;p&gt;Notice the better bass response below 400 Hz giving a truer rendering of my low voice. We also have better harmonics in the 10 to 20 kHz range, providing a more life-like sound. We can also take a look at the frequency response of the microphone, which can be found on the manufacturer’s website &lt;a href="http://www.audio-technica.com/cms/wired_mics/a0933a662b5ed0e2/index.html/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="audio-technica AT2020 Frequency Response" alt="audio-technica AT2020 Frequency Response" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/james.kovacs/at2020_5F00_freq_5F00_7992DD31.jpg" border="0" height="387" width="588"&gt; &lt;/p&gt;
&lt;p&gt;Note the flat response curve across the entire range of frequencies. This means that the microphone records all frequencies with equal efficiency, which results in little distortion of the raw sound. For comparison, I would expect the response curve for the ZX-6000 to drop to virtually zero above 4 kHz and show attenuation below 400 Hz. You want a flat response curve for your microphone as it will not colour or distort the recorded audio.&lt;/p&gt;
&lt;p&gt;I should note that both the LifeChat LX-3000 and ZX-6000 have hardware noise cancellation. (Noise cancellation will remove an annoying background hum originating from fans, pumps, and other sources of low background noise. It can’t do anything to clean up dogs barking, children screaming, or other sudden noises that disrupt your recording sessions.) Applying software noise cancellation on either of these microphones has little additional benefit. The audio-technica AT2020 does not have hardware noise cancellation and benefits from applying software noise cancellation. Assuming you are working in a quiet environment the audio quality of the AT2020 without noise cancellation is still better than the LX-3000 and far superior with noise cancellation. Software noise cancellation usually involves little more than selecting a checkbox in programs like &lt;a href="http://www.techsmith.com/camtasia.asp"&gt;TechSmith Camtasia Studio&lt;/a&gt; or similar recording packages. You can perform noise removal using Audacity too, though it’s a bit more work as you have to manually select a quiet region with just the background noise that you want to subtract.&lt;/p&gt;
&lt;p&gt;The LX-3000 is a great microphone for conference calls and gaming. It is a good, though not great, microphone for recording podcasts/screencasts/webcasts. It is inexpensive ($30 to $50), easy to use, and can be bought at most computer stores. If you’re just getting started, this is a good microphone to buy.&lt;/p&gt;
&lt;p&gt;If you’re looking to take your audio to the next level, the audio-technica AT2020 is a great semi-pro microphone that you can pick up at reasonable cost. You’ll have to go to an audio specialty store as you won’t find these in your regular computer stores. I purchased mine at &lt;a href="http://www.long-mcquade.com/"&gt;Long &amp;amp; McQuade&lt;/a&gt;, which is a chain of well-respected Canadian musical instrument stores. Now what is a reasonable cost? You’ll need more than just a microphone. You’ll also need a pre-amp to power the microphone as semi-pro and pro microphones don’t have high enough output to jack directly into your computer microphone port. You’ll need a pop filter (which prevents “p” and “t” sounds from making “popping” sounds in your audio), a mic stand, an XLR cable for mic to preamp, and a 1/4” to 1/4” male cable for preamp to computer (or 1/4” to 1/8” male if you are using a normal mic-in on your computer).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;     
&lt;tr&gt;
&lt;th&gt;&lt;b&gt;Component&lt;/b&gt;&lt;/th&gt;        &lt;th&gt;&lt;b&gt;Price*&lt;/b&gt;&lt;/th&gt;     
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.long-mcquade.com/products/485/Pro_Audio_Recording/Microphones/Audio-Technica/AT2020_Condenser_Microphone.htm"&gt;audio-technica AT2020&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$120&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.long-mcquade.com/products/105/Pro_Audio_Recording/Mic_Preamps_DI_Boxes/ART_Pro_Audio/TubeMP_Tube_Mic_Preamp.htm"&gt;ART TubeMP Tube Mic Preamp&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.long-mcquade.com/products/1733/Pro_Audio_Recording/Accessories/Apex_Electronics/Deluxe_Pop_Filter_with_Clip.htm"&gt;Pop Filter&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="http://www.long-mcquade.com/products/1722/Pro_Audio_Recording/Stands/Apex_Electronics/Heavy_Duty_Tilting_Telescopic_Stand.htm"&gt;Mic Stand&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 Cables (XLR &amp;amp; 1/4”-1/4”)&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Total&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;$229&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;* Prices are in Canadian dollars.&lt;/p&gt;
&lt;p&gt;You can get the same microphone (AT2020) with a USB option, but at a higher cost of $170, which is basically the cost of the preamp and cables. The TubeMP preamp has an actual vacuum tube that gives a warmth to the sound that is hard to achieve otherwise. Given the similar costs, I would personally err on the side of using a tube preamp over USB.&lt;/p&gt;
&lt;p&gt;You might want to invest in a decent sound card, such as a &lt;a href="http://support.creative.com/Products/ProductDetails.aspx?catID=1&amp;amp;CatName=sound+blaster&amp;amp;subCatID=208&amp;amp;subCatName=X-Fi&amp;amp;prodID=14065&amp;amp;prodName=X-Fi+Platinum"&gt;Creative Labs X-Fi Platinum&lt;/a&gt; or similar card, which has better audio recording qualities than the audio-in that comes on your motherboard. It’s hard to find the X-Fi cards anymore. So you’ll have to look around to find a good quality audio card, but expect to spend $100 to $200 on the audio card alone. Remember your audio is going to be no better than the weakest link in the chain. &lt;/p&gt;
&lt;p&gt;Is $229 of the audio-technica AT2020 worth the improved audio over the $30 to $50 LifeChat LX-3000? That’s up to you to decide.&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=1067826" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeBetter/~4/thg-RSuQ_Ho" height="1" width="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/ODhZZZgWVrY" height="1" width="1"/&gt;</summary><author><name>james.kovacs</name></author><source gr:stream-id="feed/http://codebetter.com/blogs/MainFeed.aspx"><id>tag:google.com,2005:reader/feed/http://codebetter.com/blogs/MainFeed.aspx</id><title type="html">CodeBetter.Com</title><link rel="alternate" href="http://codebetter.com" type="text/html" /></source><feedburner:origLink>http://feedproxy.google.com/~r/CodeBetter/~3/thg-RSuQ_Ho/improving-your-audio-hardware-edition.aspx</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1278431083956"><id gr:original-id="http://www.monien.net/blog/?p=307">tag:google.com,2005:reader/item/9f3f32d85bcad648</id><category term="Miscellaneous" /><title type="html">Creating multiple objects using try-finally</title><published>2010-07-06T14:37:43Z</published><updated>2010-07-06T14:37:43Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/wW5Tp7hptwI/" type="text/html" /><content xml:base="http://www.monien.net/blog" type="html">&lt;p&gt;One of the most used object-oriented patterns is probably this one:&lt;/p&gt;
&lt;pre&gt;
foo := TFoo.create;
try
  //do something with foo
finally
  foo.free;
end;
&lt;/pre&gt;
&lt;p&gt;It basically means, that if you create an instance of some class and if there is no “owner” who takes care of the new instance’s life cycle, then it is your responsibility to destroy the instance again, as soon as you are done with it.&lt;/p&gt;
&lt;p&gt;If you don’t care about freeing the objects you created, then you will get “memory leaks”, i.e. you app will use (possibly a lot) more memory as it should.&lt;/p&gt;
&lt;p&gt;The technique above is clear and simple, but what if you have more than one object that is needed in a routine? Line them up?&lt;/p&gt;
&lt;pre&gt;
foo := TFoo.create;
bar := TBar.create;
try
  //do something with foo and bar
finally
  foo.free;
  bar.free;
end;
&lt;/pre&gt;
&lt;p&gt;Looks good, and I see this pattern frequently – but hold on! What happens if there is an exception when TBar is created? Right, foo won’t be destroyed in that case. So maybe handle it like this then:&lt;/p&gt;
&lt;pre&gt;
foo := TFoo.create;
try
  bar := TBar.create;
  try
    //do something with foo and bar
  finally
    bar.free;
  end;
finally
  foo.free;
end;
&lt;/pre&gt;
&lt;p&gt;In theory this would be the correct way, and there are a lot of examples that work like that. But look at the code – right: looks really ugly, esp. if we extend that to even more objects being created. Apart from readability there is also some performance hit: every try-frame needs some extra CPU cycles, which may sum up if your routine is time critical already.&lt;/p&gt;
&lt;p&gt;My suggestion is this one:&lt;/p&gt;
&lt;pre&gt;
foo := nil;
bar := nil;
try
  foo := TFoo.create;
  bar := TBar.create;
  //do something with foo and bar
finally
  bar.free;
  foo.free;
end;
&lt;/pre&gt;
&lt;p&gt;Now lets discuss some questions about this pattern:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Didn’t we learn, that calls to “Create” have to be made &lt;strong&gt;outside&lt;/strong&gt; the try-finally block?&lt;/em&gt;&lt;br&gt;
No, not really. In fact it doesn’t matter where you create an instance of a class. The first example (which is mentioned in many articles) only suggests this, because it’s easy to do so with just one object.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If TBar.create fails, what happens with its bar.free counter part? Wouldn’t it actually be executed on some not “really created” object?&lt;/em&gt;&lt;br&gt;
No, in fact bar.free is special method, which can safely be called even on variables pointing to NIL. Free checks if self&amp;lt;&amp;gt;nil and only then the actual destructor is called.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Why did you initialize fo and bar with NIL?&lt;/em&gt;&lt;br&gt;
Because otherwise they might have random values. Esp. if they are declared as local variables. And we need NIL initialized variables so that “free” does not call random code in the case of an exception in one of the create calls.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If TBar.create fails with an exception, wouldn’t be there the chance that some address value would have been written to bar already – so that bar.free would be executed on some half initialized instance?&lt;/em&gt;&lt;br&gt;
No, if TBar.Create fails with an exception, then the class function “create” would (like any other function) return NO value at all. bar would keep its original value that is. &lt;/p&gt;


&lt;div&gt;
&lt;ul&gt;
		&lt;li&gt;
			&lt;a href="http://www.shareaholic.com/api/share/?title=Creating+multiple+objects+using+try-finally&amp;amp;link=http://www.monien.net/blog/index.php/2010/07/creating-multiple-objects-using-try-finally/&amp;amp;notes=One%20of%20the%20most%20used%20object-oriented%20patterns%20is%20probably%20this%20one%3A%0D%0A%5Bsourcecode%20lang%3Ddelphi%5D%0D%0Afoo%20%3A%3D%20TFoo.create%3B%0D%0Atry%0D%0A%20%20%2F%2Fdo%20something%20with%20foo%0D%0Afinally%0D%0A%20%20foo.free%3B%0D%0Aend%3B%0D%0A%5B%2Fsourcecode%5D%0D%0A%0D%0AIt%20basically%20means%2C%20that%20if%20you%20create%20an%20instance%20of%20some%20class%20and%20if%20there%20is%20no%20%22owner%22%20who%20takes%20care%20&amp;amp;short_link=&amp;amp;shortener=tinyurl&amp;amp;shortener_key=&amp;amp;v=1&amp;amp;apitype=1&amp;amp;apikey=8afa39428933be41f8afdb8ea21a495c&amp;amp;source=Shareaholic&amp;amp;template=%24%7Btitle%7D+-+%24%7Bshort_link%7D&amp;amp;service=7&amp;amp;tags=&amp;amp;ctype=" rel="nofollow" title="Tweet This!"&gt;Tweet This!&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
			&lt;a href="http://www.monien.net/blog/index.php/2010/07/creating-multiple-objects-using-try-finally/feed" rel="nofollow" title="Subscribe to the comments for this post?"&gt;Subscribe to the comments for this post?&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
			&lt;a href="http://www.shareaholic.com/api/share/?title=Creating+multiple+objects+using+try-finally&amp;amp;link=http://www.monien.net/blog/index.php/2010/07/creating-multiple-objects-using-try-finally/&amp;amp;notes=One%20of%20the%20most%20used%20object-oriented%20patterns%20is%20probably%20this%20one%3A%0D%0A%5Bsourcecode%20lang%3Ddelphi%5D%0D%0Afoo%20%3A%3D%20TFoo.create%3B%0D%0Atry%0D%0A%20%20%2F%2Fdo%20something%20with%20foo%0D%0Afinally%0D%0A%20%20foo.free%3B%0D%0Aend%3B%0D%0A%5B%2Fsourcecode%5D%0D%0A%0D%0AIt%20basically%20means%2C%20that%20if%20you%20create%20an%20instance%20of%20some%20class%20and%20if%20there%20is%20no%20%22owner%22%20who%20takes%20care%20&amp;amp;short_link=&amp;amp;shortener=tinyurl&amp;amp;shortener_key=&amp;amp;v=1&amp;amp;apitype=1&amp;amp;apikey=8afa39428933be41f8afdb8ea21a495c&amp;amp;source=Shareaholic&amp;amp;template=&amp;amp;service=2&amp;amp;tags=&amp;amp;ctype=" rel="nofollow" title="Share this on del.icio.us"&gt;Share this on del.icio.us&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
			&lt;a href="http://www.shareaholic.com/api/share/?title=Creating+multiple+objects+using+try-finally&amp;amp;link=http://www.monien.net/blog/index.php/2010/07/creating-multiple-objects-using-try-finally/&amp;amp;notes=One%20of%20the%20most%20used%20object-oriented%20patterns%20is%20probably%20this%20one%3A%0D%0A%5Bsourcecode%20lang%3Ddelphi%5D%0D%0Afoo%20%3A%3D%20TFoo.create%3B%0D%0Atry%0D%0A%20%20%2F%2Fdo%20something%20with%20foo%0D%0Afinally%0D%0A%20%20foo.free%3B%0D%0Aend%3B%0D%0A%5B%2Fsourcecode%5D%0D%0A%0D%0AIt%20basically%20means%2C%20that%20if%20you%20create%20an%20instance%20of%20some%20class%20and%20if%20there%20is%20no%20%22owner%22%20who%20takes%20care%20&amp;amp;short_link=&amp;amp;shortener=tinyurl&amp;amp;shortener_key=&amp;amp;v=1&amp;amp;apitype=1&amp;amp;apikey=8afa39428933be41f8afdb8ea21a495c&amp;amp;source=Shareaholic&amp;amp;template=&amp;amp;service=3&amp;amp;tags=&amp;amp;ctype=" rel="nofollow" title="Digg this!"&gt;Digg this!&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
			&lt;a href="http://www.shareaholic.com/api/share/?title=Creating+multiple+objects+using+try-finally&amp;amp;link=http://www.monien.net/blog/index.php/2010/07/creating-multiple-objects-using-try-finally/&amp;amp;notes=One%20of%20the%20most%20used%20object-oriented%20patterns%20is%20probably%20this%20one%3A%0D%0A%5Bsourcecode%20lang%3Ddelphi%5D%0D%0Afoo%20%3A%3D%20TFoo.create%3B%0D%0Atry%0D%0A%20%20%2F%2Fdo%20something%20with%20foo%0D%0Afinally%0D%0A%20%20foo.free%3B%0D%0Aend%3B%0D%0A%5B%2Fsourcecode%5D%0D%0A%0D%0AIt%20basically%20means%2C%20that%20if%20you%20create%20an%20instance%20of%20some%20class%20and%20if%20there%20is%20no%20%22owner%22%20who%20takes%20care%20&amp;amp;short_link=&amp;amp;shortener=tinyurl&amp;amp;shortener_key=&amp;amp;v=1&amp;amp;apitype=1&amp;amp;apikey=8afa39428933be41f8afdb8ea21a495c&amp;amp;source=Shareaholic&amp;amp;template=&amp;amp;service=257&amp;amp;tags=&amp;amp;ctype=" rel="nofollow" title="Post on Google Buzz"&gt;Post on Google Buzz&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
			&lt;a href="http://www.shareaholic.com/api/share/?title=Creating+multiple+objects+using+try-finally&amp;amp;link=http://www.monien.net/blog/index.php/2010/07/creating-multiple-objects-using-try-finally/&amp;amp;notes=One%20of%20the%20most%20used%20object-oriented%20patterns%20is%20probably%20this%20one%3A%0D%0A%5Bsourcecode%20lang%3Ddelphi%5D%0D%0Afoo%20%3A%3D%20TFoo.create%3B%0D%0Atry%0D%0A%20%20%2F%2Fdo%20something%20with%20foo%0D%0Afinally%0D%0A%20%20foo.free%3B%0D%0Aend%3B%0D%0A%5B%2Fsourcecode%5D%0D%0A%0D%0AIt%20basically%20means%2C%20that%20if%20you%20create%20an%20instance%20of%20some%20class%20and%20if%20there%20is%20no%20%22owner%22%20who%20takes%20care%20&amp;amp;short_link=&amp;amp;shortener=tinyurl&amp;amp;shortener_key=&amp;amp;v=1&amp;amp;apitype=1&amp;amp;apikey=8afa39428933be41f8afdb8ea21a495c&amp;amp;source=Shareaholic&amp;amp;template=&amp;amp;service=40&amp;amp;tags=&amp;amp;ctype=" rel="nofollow" title="Share this on Reddit"&gt;Share this on Reddit&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
			&lt;a href="http://www.shareaholic.com/api/share/?title=Creating+multiple+objects+using+try-finally&amp;amp;link=http://www.monien.net/blog/index.php/2010/07/creating-multiple-objects-using-try-finally/&amp;amp;notes=One%20of%20the%20most%20used%20object-oriented%20patterns%20is%20probably%20this%20one%3A%0D%0A%5Bsourcecode%20lang%3Ddelphi%5D%0D%0Afoo%20%3A%3D%20TFoo.create%3B%0D%0Atry%0D%0A%20%20%2F%2Fdo%20something%20with%20foo%0D%0Afinally%0D%0A%20%20foo.free%3B%0D%0Aend%3B%0D%0A%5B%2Fsourcecode%5D%0D%0A%0D%0AIt%20basically%20means%2C%20that%20if%20you%20create%20an%20instance%20of%20some%20class%20and%20if%20there%20is%20no%20%22owner%22%20who%20takes%20care%20&amp;amp;short_link=&amp;amp;shortener=tinyurl&amp;amp;shortener_key=&amp;amp;v=1&amp;amp;apitype=1&amp;amp;apikey=8afa39428933be41f8afdb8ea21a495c&amp;amp;source=Shareaholic&amp;amp;template=&amp;amp;service=10&amp;amp;tags=&amp;amp;ctype=" rel="nofollow" title="Share this on Technorati"&gt;Share this on Technorati&lt;/a&gt;
		&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;div style="font-size:10px!important"&gt;&lt;a href="http://www.shareaholic.com/?src=pub"&gt;Get Shareaholic&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/wW5Tp7hptwI" height="1" width="1"/&gt;</content><author><name>Olaf Monien</name></author><source gr:stream-id="feed/http://www.monien.net/blog/index.php/feed/"><id>tag:google.com,2005:reader/feed/http://www.monien.net/blog/index.php/feed/</id><title type="html">Olaf&amp;#39;s Thoughts About Development</title><link rel="alternate" href="http://www.monien.net/blog" type="text/html" /></source><feedburner:origLink>http://www.monien.net/blog/index.php/2010/07/creating-multiple-objects-using-try-finally/</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1277976859535"><id gr:original-id="http://andy.jgknet.de/blog/?p=814">tag:google.com,2005:reader/item/2e79c9d3150d40b9</id><category term="Delphi" /><title type="html">Delphi 2009/2010 Post-Build events</title><published>2010-06-30T18:51:13Z</published><updated>2010-06-30T18:51:13Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/W0wR8JXY_uE/" type="text/html" /><content xml:base="http://andy.jgknet.de/blog" type="html">&lt;p style="text-align:justify"&gt;&lt;a href="http://andy.jgknet.de/blog/wp-content/uploads/2010/06/PostBuildEvents.png"&gt;&lt;img style="margin-left:10px" title="Post-Build events edit dialog" src="http://andy.jgknet.de/blog/wp-content/uploads/2010/06/PostBuildEvents-253x300.png" alt="" width="253" height="300"&gt;&lt;/a&gt;Have you ever wondered if it is possible to execute the “Post-Build events” only when the project was actually updated/compiled? With Delphi 2009/2010 you can do that easily by changing the “Execute when” combobox in the “Post-Build events” edit dialog to “Target is out-of-date”. At least you thought that would do the trick. Instead it disables the Post-Build event what means that it is never executed.&lt;br&gt;
 I did some research on this because I needed this functionality. Without it the “Execute when” = “Always” setting tells msbuild to execute the post-build script even if the compiler didn’t do anything. And that causes msbuild to build targets that don’t need to be built.&lt;/p&gt;
&lt;p style="text-align:justify"&gt;But what is the problem with “Target is out-of-date”. Let’s have a look into the msbuild script that executes the Post-Build events. The “PostBuildEvent” target in $(BDS)\bin\CodeGear.Common.Targets is declared as:&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;

&lt;div&gt;&lt;div&gt;&lt;pre style="font-family:monospace"&gt;&lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;Target Name=&amp;quot;PostBuildEvent&amp;quot;
        Condition=&amp;quot; &amp;#39;$(PostBuildEvent)&amp;#39;!=&amp;#39;&amp;#39;  And &amp;#39;$(KibitzCompile)&amp;#39;==&amp;#39;&amp;#39;
        and ( &amp;#39;$(RunPostBuildEvent)&amp;#39;==&amp;#39;Always&amp;#39; or &amp;#39;$(RunPostBuildEvent)&amp;#39;==&amp;#39;&amp;#39; or &amp;#39;$(PreOutputTimeStamp)&amp;#39;!=&amp;#39;$(PostOutputTimeStamp)&amp;#39; )&amp;quot;
        DependsOnTargets=&amp;quot;$(PostBuildEventDependsOn)&amp;quot;&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;Exec Command=&amp;quot;$(PostBuildEvent)&amp;quot;  IgnoreExitCode=&amp;quot;$(PostBuildEventIgnoreExitCode)&amp;quot; WorkingDirectory=&amp;quot;$(OutDir)&amp;quot;/&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;/Target&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s see what msbuild with “/v:diag” tells us about this target.&lt;/p&gt;
&lt;pre style="padding-left:30px"&gt;'$(RunPostBuildEvent)'=='Always' or '$(RunPostBuildEvent)'=='' or
  '$(PreOutputTimeStamp)'!='$(PostOutputTimeStamp)'&lt;/pre&gt;
&lt;p&gt;is evaluated to&lt;/p&gt;
&lt;pre style="padding-left:30px"&gt;'OutOfDate'=='Always' or 'OutOfDate'=='' or ''!=''&lt;/pre&gt;
&lt;p style="text-align:justify"&gt;The first two conditions are ok and mean that we have to look at the third condition for our out-of-date check. But what is with the third condition? Why is it an empty string comparison that is always false? And where do PreOutputTimeStamp and PostOutputTimeStamp come from? They are declared some lines about the “PostBuildEvent” target.&lt;/p&gt;

&lt;div&gt;&lt;div&gt;&lt;pre style="font-family:monospace"&gt;&lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;Target Name=&amp;quot;_PreOutputTimeStamp&amp;quot;&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;CreateItem Include=&amp;quot;%(OutputFile.ModifiedTime)&amp;quot;&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;Output TaskParameter=&amp;quot;Include&amp;quot; PropertyName=&amp;quot;PreOutputTimeStamp&amp;quot;/&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;/CreateItem&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;/Target&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
 
&lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;Target Name=&amp;quot;_PostOutputTimeStamp&amp;quot;&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;CreateItem Include=&amp;quot;%(OutputFile.ModifiedTime)&amp;quot;&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;Output TaskParameter=&amp;quot;Include&amp;quot; PropertyName=&amp;quot;PostOutputTimeStamp&amp;quot;/&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;/CreateItem&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;/Target&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p style="text-align:justify"&gt;So the PreOutputTimeStamp is the modified time of the output file (EXE/DLL/BPL) before it was compiled and the PostOutputTimeStamp is the modified time of the same file after msbuild has done its work. But why are they empty?&lt;br&gt;
 The item “OutputFile” is not declared or set anywhere. Neither in CodeGear.Common.Targets nor in CodeGear.Delphi.Targets nor in MyProject.dproj. And that is why both msbuild properties are evaluated to empty strings.&lt;/p&gt;
&lt;p style="text-align:justify"&gt;With this knowledge I was now able to fix the this bug by adding the missing “OutputFile” item to the CodeGear.Delphi.Targets file.&lt;/p&gt;

&lt;div&gt;&lt;div&gt;&lt;pre style="font-family:monospace"&gt; &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;ItemGroup&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;_MSBuildProjectFullPath Include=&amp;quot;$(MSBuildProjectFullPath)&amp;quot;/&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;_DependencyCheckOutputName Include=&amp;quot;$(DCC_DependencyCheckOutputName)&amp;quot;/&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
+   &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;OutputFile Include=&amp;quot;$(DCC_DependencyCheckOutputName)&amp;quot;/&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;
 &lt;span style="color:#ddbb00"&gt;&amp;lt;&lt;/span&gt;/ItemGroup&lt;span style="color:#ddbb00"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p style="text-align:justify"&gt;After this change the “Target is out-of-date” combobox item in the “Post-Build events” dialog started to work as expected.&lt;/p&gt;
&lt;p style="text-align:justify"&gt; &lt;/p&gt;
&lt;p style="text-align:justify"&gt;One issue solved.&lt;strong&gt; &lt;/strong&gt;But that wasn’t all that I needed for my build script. In order to reduce the file size of our massive EXE files we strip the PE format’s relocation section from the EXEs and we create and attach *.jdbg files to our EXEs. But both post-build events aren’t necessary when we debug our projects in the IDE, especially not the relocation section removal. In the IDE we want a fast edit-compile-debug turn-around. So I had to find a way to only execute those post-build events when the Release-Configuration was active.&lt;br&gt;
 Unfortunately Delphi doesn’t support this feature. But after browsing through the CodeGear.*.Targets files and reading msbuild /v:diag log files, I had the solution right there sitting in front of me. The $(OUTPUTPATH) from the post-build events are replaced by msbuild properties when msbuild processes the build script. So I had the idea of just trying to use other properties from msbuild in addition to the macros that are listed in the Post-Build events edit dialog. And with $(Config) I had the active configuration right at hand.&lt;/p&gt;

&lt;div&gt;&lt;div&gt;&lt;pre style="font-family:monospace"&gt;if &amp;quot;$(Config)&amp;quot; == &amp;quot;Release&amp;quot; (
  stripreloc.exe ...
  linkmapfile.exe ...
)&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And with the active configuration being set to “Debug”, msbuild executes this as:&lt;/p&gt;

&lt;div&gt;&lt;div&gt;&lt;pre style="font-family:monospace"&gt;if &amp;quot;Debug&amp;quot; == &amp;quot;Release&amp;quot; (
  stripreloc.exe ...
  linkmapfile.exe ...
)&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p style="text-align:justify"&gt;Now that I have solved the build script issues, I can turn to all the other “things” that I have to solve, think about and develop before all my co-workers can start working with the new Delphi IDE.&lt;/p&gt;
&lt;p style="text-align:justify"&gt;Those “things” are things like keeping the components as part of the project to make it possible to update to a new component version without breaking older project versions. And I’m not speaking of using the “-r” IDE command line option. That’s what we used in the older Delphi version. I’m speaking of opening a project from the 1.0 branch, closing it and opening the same project from the 7.0 branch that requires newer versions of the components. Furthermore the components are in the project’s svn folder, so they have the same revision number. (Our old svn “layout” was to have a separate svn repository for the  components) And if you svn-update and somebody has changed the components, the IDE automatically compiles them and loads them when you open the project. And today this IDE plugin passed it’s final tests.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/W0wR8JXY_uE" height="1" width="1"/&gt;</content><author><name>Andreas Hausladen</name></author><source gr:stream-id="feed/http://andy.jgknet.de/blog/?feed=rss2"><id>tag:google.com,2005:reader/feed/http://andy.jgknet.de/blog/?feed=rss2</id><title type="html">Andy&amp;#39;s Blog and Tools</title><link rel="alternate" href="http://andy.jgknet.de/blog" type="text/html" /></source><feedburner:origLink>http://andy.jgknet.de/blog/2010/06/delphi-20092010-post-build-events/</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1276849695832"><id gr:original-id="http://alex.ciobanu.org/?p=358">tag:google.com,2005:reader/item/72c653c677cd12e8</id><category term="Programming" /><category term="BSD" /><category term="DeHL" /><category term="delphi" /><category term="EMBT" /><category term="LinkedIn" /><category term="RTL" /><category term="RTTI" /><title type="html">DeHL 0.8.3</title><published>2010-06-17T21:27:59Z</published><updated>2010-06-17T21:27:59Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/50PM3UzbZMU/" type="text/html" /><content xml:base="http://alex.ciobanu.org/" type="html">&lt;p&gt;&lt;a rel="attachment wp-att-242" href="http://alex.ciobanu.org/?attachment_id=242"&gt;&lt;img title="DeHL" src="http://alex.ciobanu.org/files/uploads/2009/06/Logo_2.png" alt="DeHL" width="100" height="100"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I will be brief as usual — version 0.8.3 of DeHL is out. The downloads can be found on &lt;a href="http://code.google.com/p/delphilhlplib/downloads/list"&gt;this&lt;/a&gt; page and changelog on &lt;a href="http://code.google.com/p/delphilhlplib/source/browse/tags/0.8.3/changelog.txt"&gt;this&lt;/a&gt; page. This release “fixes” some of the things I wanted fixed for a long time, so it seemed this is the perfect moment for this to happen. A new unit is introduced — &lt;em&gt;DeHL.Tuples&lt;/em&gt; — which brings seven generic &lt;strong&gt;Tuple&amp;lt;…&amp;gt;&lt;/strong&gt; types. I have also finished moving away from Integer and Cardinal to NativeInt and NativeUInt through all DeHL.&lt;/p&gt;
&lt;p&gt;Breaking changes are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;DeHL.Converter&lt;/em&gt; was renamed to &lt;em&gt;DeHL.Conversion&lt;/em&gt;. This name change was done mostly to reflect the nature of the unit. It does not contain one simple class anymore. Now there is a fully featured conversion system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TBinaryTree&amp;lt;T&amp;gt;&lt;/strong&gt; (in &lt;em&gt;DeHL.Collections.BinaryTree&lt;/em&gt;) is no more. It was written way in the beginnings of the project and was buggy, incomplete and utterly useless.&lt;/li&gt;
&lt;li&gt;And the most visible and breaking of all changes is the removal of &lt;strong&gt;TKeyValuePair&amp;lt;TKey, TValue&amp;gt;&lt;/strong&gt; (in &lt;em&gt;DeHL.KeyValuePair&lt;/em&gt;). It was replaced with &lt;strong&gt;KVPair&amp;lt;TKey, TValue&amp;gt;&lt;/strong&gt; (in &lt;em&gt;DeHL.Tuples&lt;/em&gt;). The easiet way to get over this change is to find and replace all TKeyValuePair instances with KVPair and all DeHL.KeyValuePair uses with DeHL.Tuples.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now, obviously an example using Tuples:&lt;/p&gt;
&lt;pre&gt;
uses
  SysUtils, DeHL.Tuples;

{ If you are lazy and do not wish to declare a new record type
  to be used as result. Use Tuple&amp;lt;..&amp;gt; do to that. }
function GiveMeSomeData(): Tuple&amp;lt;String, Integer, Integer&amp;gt;;
begin
  { ... Do some processing ... }
  Result := Tuple.Create(&amp;#39;Some data&amp;#39;, 100, -99);
end;

var
  LResult: Tuple&amp;lt;String, Integer, Integer&amp;gt;;
begin
  { Obtain the result }
  LResult := GiveMeSomeData();

  { And write the results to the console }
  with LResult do
    WriteLn(&amp;#39;Something was done with result: &amp;#39;, Value1, &amp;#39;, &amp;#39;,
      Value2, &amp;#39;, &amp;#39;, Value3, &amp;#39;!&amp;#39;);
end.
&lt;/pre&gt;
&lt;p&gt;The new conversion engine handles most of the possible conversions and also allows registering custom ones:&lt;/p&gt;
&lt;pre&gt;
uses
  SysUtils,
  DeHL.Conversion,
  DeHL.Collections.List;

type
  { Declare some type that cannot be converted into integer directly.
    We&amp;#39;re making up an &amp;quot;int&amp;quot;. }
  TRecordInt = packed record
    FValueAsString: string;
    FSign: Boolean;

    constructor Create(const AInt: Integer);
  end;

{ TRecordInt }

constructor TRecordInt.Create(const AInt: Integer);
begin
  { Decompose an int }
  FValueAsString := IntToStr(Abs(AInt));
  FSign := (AInt &amp;lt; 0);
end;

var
  LInputList: TList&amp;lt;TRecordInt&amp;gt;;
  S: String;
  I: Integer;
begin
  { Create a list of TRecordInt }
  LInputList := TList&amp;lt;TRecordInt&amp;gt;.Create();

  { Fill it with some random values (positive and negative) }
  for I := 0 to 10 do
    LInputList.Add(TRecordInt.Create(Random(MaxInt) - (MaxInt div 2)));

  { Now comes the interesting part ... register a custom converter
    from TRecordInt to Integer }
  TConverter&amp;lt;TRecordInt, Integer&amp;gt;.Method :=
    function(const AIn: TRecordInt; out AOut: Integer): Boolean
    begin
      { Convert the TRecordInt back to an integer }
      Result := TryStrToInt(AIn.FValueAsString, AOut);
      if Result and AIn.FSign then
        AOut := -AOut;
    end;

  { Now print the values to the console. Convert them from TRecordInt to
    Integer then to String }
  for S in LInputList.Op.Cast&amp;lt;Integer&amp;gt;.Op.Cast&amp;lt;String&amp;gt; do
    WriteLn(S);
end.
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;TConverter&lt;/strong&gt; is also smart enough to figure out that &lt;em&gt;“type MyInt = type Integer”&lt;/em&gt; is actually equivalent to &lt;strong&gt;Integer&lt;/strong&gt;. If there is no explicit custom conversion method registered for it the converter for the standard type will be selected is possible. In the worst case, when TConverter cannot convert directly between the given types, it falls back to Variant conversion (using &lt;em&gt;TType.TryConvertToVariant&lt;/em&gt; and &lt;em&gt;TType.TryConvertFromVariant&lt;/em&gt;) which all types registered with DeHL’s type system,  if possible, should implement.&lt;/p&gt;
&lt;p&gt;Well, that’s all for today,&lt;strong&gt;&lt;br&gt;
Have Fun!&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/50PM3UzbZMU" height="1" width="1"/&gt;</content><author><name>alex</name></author><source gr:stream-id="feed/http://alex.ciobanu.org/?feed=rss2"><id>tag:google.com,2005:reader/feed/http://alex.ciobanu.org/?feed=rss2</id><title type="html">YAPB</title><link rel="alternate" href="http://alex.ciobanu.org" type="text/html" /></source><feedburner:origLink>http://alex.ciobanu.org/?p=358</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1276551860324"><id gr:original-id="91d46819-8472-40ad-a661-2c78acb4018c:10023724">tag:google.com,2005:reader/item/68e2717c42729e76</id><category term="C#" scheme="http://blogs.msdn.com/b/cburrows/archive/tags/C_2300_/" /><category term="performance" scheme="http://blogs.msdn.com/b/cburrows/archive/tags/performance/" /><category term="arrays" scheme="http://blogs.msdn.com/b/cburrows/archive/tags/arrays/" /><title type="html">The Performance of Arrays</title><published>2010-06-11T21:01:26Z</published><updated>2010-06-11T21:01:26Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/V75svokikrY/the-performance-of-arrays.aspx" type="text/html" /><summary xml:base="http://blogs.msdn.com/b/cburrows/" type="html">&lt;p&gt;Stop me if you’ve heard this one, but here’s some information about how arrays perform, and a neat trick you can do to (possibly) get some performance back.&lt;/p&gt;  &lt;h3&gt;Some background&lt;/h3&gt;  &lt;p&gt;In .NET, arrays of reference types are covariant in their element type, but not safely. &lt;a href="http://blogs.msdn.com/b/ericlippert/"&gt;Eric&lt;/a&gt;, as always, has &lt;a href="http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx"&gt;a post that goes into this more deeply&lt;/a&gt; if you want to refresh your memory. The upshot is that if you have a Derived[], you can convert it to a Base[] and use it that way. For instance,&lt;/p&gt;  &lt;pre&gt;class Base { }
class Derived : Base { }
 
class Program
{
    static void Main()
    {
        Derived[] derivedArray = new Derived[10];
        // This is the covariant conversion
        Base[] baseArray = derivedArray;
 
        for (int i = 0; i &amp;lt; baseArray.Length; ++i)
        {
            // Putting a Derived into our Base[] is ordinary polymorphism
            baseArray[i] = new Derived();
        }
    }
}&lt;/pre&gt;

&lt;p&gt;Allowing this conversion from Derived[] to Base[] is not safe because now the compiler can’t help you know if your types match up when you set array elements. In the preceding example, I can put the Derived in the array, but imagine if I had another unrelated derived class, OtherDerived. Putting those things in the array must fail, since the actual array can contain only Deriveds, and OtherDeriveds are &lt;em&gt;not&lt;/em&gt; Deriveds. In Eric’s perhaps more folksy example, “you can’t put a Turtle into an array of Giraffes.” &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre&gt;class Base { }
class Derived : Base { }
class OtherDerived : Base { }
 
class Program
{
    static void Main()
    {
        Derived[] derivedArray = new Derived[10];
        // This is the covariant conversion
        Base[] baseArray = derivedArray;
 
        for (int i = 0; i &amp;lt; baseArray.Length; ++i)
        {
            // Putting a OtherDerived into our Base[] is ordinary
            // polymorphism. However, this is going to cause a runtime
            // exception because the actual array won&amp;#39;t be able to
            // store an OtherDerived.
            baseArray[i] = new OtherDerived();
            // Unhandled Exception: System.ArrayTypeMismatchException: 
            //   Attempted to access an element as a type incompatible
            // with the array.
        }
    }
}&lt;/pre&gt;

&lt;p&gt;Well now to the point I want to address: where did that exception come from? It came from the runtime, which was in a unique position to know what the real type of the array object was, and the real type of the element. It needed to determine if the assignment was allowable and throw if not. Now if you think about this for a minute, you can see that it’s going to have to perform that check for every assignment to an array element, right? The compiler just can’t know if any assignment to a covariant array is ever going to work, and the runtime is always going to have to be there to manage the potential for failure. Can we turn that off? Does it make sense to? What does the check cost you?&lt;/p&gt;

&lt;h3&gt;A workaround&lt;/h3&gt;

&lt;p&gt;Well, if it’s doing that check for every assignment to an array, that’s probably going to cost you something. Let’s see if we can get rid of the check to determine what the cost is. Remember I said that arrays are covariant only for reference types? We’re going to use that information. If we have an array of value types, the runtime isn’t going to have to perform that check anymore, since it knows that the IL the compiler emitted wasn’t going to allow assignment of anything but that value type to that array.&lt;/p&gt;

&lt;p&gt;So if I want to have an array of reference types, but get the runtime to treat it like an array of value types, what have I got to do? Just wrap the reference type in a value type. There you go. That’s the trick. Let’s see what that does.&lt;/p&gt;

&lt;p&gt;I’m going to create a simple value type that merely holds a reference. I am even going to make it generic. And to make this as dead-simple as I can, that’s all I’ll do. You could imagine a potentially easier-to-use version of this code that has implicit conversions and nice constructors, but let’s not do any of that.&lt;/p&gt;

&lt;pre&gt;struct Reference&amp;lt;T&amp;gt; where T : class
{
    public T Value;
}&lt;/pre&gt;

&lt;p&gt;Ok, so, wow, what is that thing? It’s no bigger than the reference we started with. And if I want to make an array of them in order to get rid of covariance, I can. And here’s how I’d use it.&lt;/p&gt;

&lt;pre&gt;class Base { }
class Derived : Base { }
 
class Program
{
    static void Main()
    {
        Reference&amp;lt;Base&amp;gt;[] baseArray = new Reference&amp;lt;Base&amp;gt;[10];
 
        for (int i = 0; i &amp;lt; baseArray.Length; ++i)
        {
            baseArray[i] = new Reference&amp;lt;Base&amp;gt; { Value = new Derived() };
        }
    }
}&lt;/pre&gt;

&lt;p&gt;Now I have an array assignment that doesn’t need the runtime to perform a check anymore, and the reason is because it’s impossible for there to be anything in “baseArray” except for an array of the exact type I said. The struct-ness of Reference&amp;lt;T&amp;gt; prevents the possibility of anyone having performed a covariant conversion as existed in our previous examples. So I got rid of that check, right? But I added the initialization of a value type. Did I win or lose? Let’s do some timing to figure it out.&lt;/p&gt;

&lt;h3&gt;The experiment&lt;/h3&gt;

&lt;p&gt;Here’s my code. I’m going to time two different things: First, I’ll put a lot of Deriveds into a Base[], and then I’ll put a lot of Reference&amp;lt;Base&amp;gt;s that hold Deriveds into a Reference&amp;lt;Base&amp;gt;. I’m using huge arrays just because I want to prove to myself that the jitter isn’t going to lift some of these operations out of the loop. And I’m producing Release binaries that will run on the 32-bit framework on my 64-bit machine. I’ll time each example a few times to be sure. Here’s the code.&lt;/p&gt;

&lt;pre&gt;class Base { }
class Derived : Base { }
 
struct Reference&amp;lt;T&amp;gt; where T : class
{
    public T Value;
}
 
class Program
{
    const int Count = 1 &amp;lt;&amp;lt; 27;
 
    static void Main()
    {
        Stopwatch watch = new Stopwatch();
 
        TestReferenceArray(watch);
        TestReferenceArray(watch);
        TestReferenceArray(watch);
 
        TestValueArray(watch);
        TestValueArray(watch);
        TestValueArray(watch);
    }
 
    static Base[] TestReferenceArray(Stopwatch watch)
    {
        Base[] array = new Base[Count];
        var element = new Derived();
 
        watch.Restart();
        for (int i = 0; i &amp;lt; Count; ++i)
        {
            array[i] = element;
        }
        watch.Stop();
        Console.WriteLine(watch.ElapsedMilliseconds);
 
        return array;
    }
 
    static Reference&amp;lt;Base&amp;gt;[] TestValueArray(Stopwatch watch)
    {
        Reference&amp;lt;Base&amp;gt;[] array = new Reference&amp;lt;Base&amp;gt;[Count];
        var element = new Derived();
 
        watch.Restart();
        for (int i = 0; i &amp;lt; Count; ++i)
        {
            array[i] = new Reference&amp;lt;Base&amp;gt; { Value = element };
        }
        watch.Stop();
        Console.WriteLine(watch.ElapsedMilliseconds);
 
        return array;
    }
}&lt;/pre&gt;

&lt;p&gt;Have a seat. Here’s what it prints out.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;2507 
    &lt;br&gt;2471 

    &lt;br&gt;2474 

    &lt;br&gt;595 

    &lt;br&gt;607 

    &lt;br&gt;593&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wow! That’s a huge time difference, and a big win. It’s FOUR TIME FASTER! I wouldn’t blame you for thinking that you have to go to your code base right now and eliminate arrays of reference types from it; but hold on a second. That’s not the whole story.&lt;/p&gt;

&lt;h3&gt;Issue #1: Are the types exact?&lt;/h3&gt;

&lt;p&gt;In the example that I timed, I was putting a Derived into arrays with element type Base. The types weren’t the same, and therefore the check that the runtime performed had to be complicated by doing something like walking an inheritance hierarchy. But what if I were putting Bases into the Base array. What do the times look like then? (I won’t replicate the code here; just replace “new Derived()” with “new Base()” everywhere).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;805 
    &lt;br&gt;775 

    &lt;br&gt;771 

    &lt;br&gt;593 

    &lt;br&gt;593 

    &lt;br&gt;599&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oh, that’s much more reasonable. The lesson here is that for my scenario, if I’m not making use of polymorphism, I have much less to be worried about.&lt;/p&gt;

&lt;h3&gt;Issue #2: Which runtime exactly?&lt;/h3&gt;

&lt;p&gt;I said that I was doing tests on the 32-bit framework on my 64-bit machine. I ensured that by building my binaries “x86,” which is the default for VS2010. What if I instead build them “Any CPU” so that I can run the test on the 64-bit framework? Under those conditions, I am swapping out the whole stack that my tests run on for a whole different runtime. Let’s see what the numbers are then.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;2102 
    &lt;br&gt;2057 

    &lt;br&gt;2055 

    &lt;br&gt;789 

    &lt;br&gt;784 

    &lt;br&gt;784&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok, still faster, but not by as big a factor. What about for the exact type case?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;861 
    &lt;br&gt;848 

    &lt;br&gt;846 

    &lt;br&gt;792 

    &lt;br&gt;790 

    &lt;br&gt;817&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nearly the same! So my example seems to be not as big a deal for 64-bit processes. I am not sure why. There is another oddity here that I can’t explain: when I build Debug binaries, the Reference&amp;lt;T&amp;gt; trick makes my example about three times SLOWER. I have no idea why.&lt;/p&gt;

&lt;h3&gt;Issue #3: My example is not your scenario&lt;/h3&gt;

&lt;p&gt;I tried to make the thing I was timing as simple as possible. But I’m using relatively &lt;em&gt;a lot&lt;/em&gt; of array assignments. Do you do that much? Probably not. I’m not doing any I/O and not waiting on any user interaction, are you? I also have a giant array and I’m clearly blowing out the CPU cache in my for loops. Does your code do that? I’m assigning arrays in a tight loop with a known upper bound. Are you? Does the jitter lift the bounds checking out of the loop, and how would that check compare with the assignment compatibility check? &lt;/p&gt;

&lt;p&gt;My point is that as with any performance timing, there are a lot of variables and a lot of considerations. If you want to make your program perform better using this trick, you need to try it and then time it yourself. I am &lt;em&gt;not&lt;/em&gt; saying that .NET arrays are slower than they need to be or unsuited for your application. But it’s a fun experiment to try; how many milliseconds faster can you make your scenario, and is it worth the cost? Were you using the covariance of arrays in your code, and therefore ineligible to even consider this trick?&lt;/p&gt;

&lt;h3&gt;Why?&lt;/h3&gt;

&lt;p&gt;Why does C# have these unsafe covariant arrays to begin with? I was not here at the time, but I can confidently say that the CLR needed them because they needed to support languages that have array covariance. One example of such a language (in fact, probably the interesting example) is Java. C# has them both because the CLR has them and because it was a clear goal to that if users were porting existing code to C#, they were met with as few hurdles as possible. Also, there would have been complications with supporting both covariant arrays and invariant arrays in the same runtime; imagine the confusion users and compiler-writers would face trying to interop between the two. The language design notes from 1999 bear out these claims.&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10023724" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/V75svokikrY" height="1" width="1"/&gt;</summary><author><name>cburrows</name></author><source gr:stream-id="feed/http://blogs.msdn.com/cburrows/rss.xml"><id>tag:google.com,2005:reader/feed/http://blogs.msdn.com/cburrows/rss.xml</id><title type="html">Chris Burrows&amp;#39; [Old] Blog</title><link rel="alternate" href="http://blogs.msdn.com/b/cburrows/" type="text/html" /></source><feedburner:origLink>http://blogs.msdn.com/b/cburrows/archive/2010/06/11/the-performance-of-arrays.aspx</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1276550951957"><id gr:original-id="http://blog.marcocantu.com/blog/hundred_thousand_lines_unit.html">tag:google.com,2005:reader/item/ea02db495d37ed36</id><title type="html">Hundred Thousand Lines in a Unit</title><published>2010-06-14T10:12:48Z</published><updated>2010-06-14T10:12:48Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/489Wy0DUmdo/hundred_thousand_lines_unit.html" type="text/html" /><content xml:base="http://blog.marcocantu.com/blog_rss2.xmldata" type="html">&lt;p&gt;At a recent event, a person mentioned he had problems with the debugger with a very large unit (as you can see in &lt;a href="http://blog.marcocantu.com/blog/delphi_day_2010_summary.html"&gt;the questions&lt;/a&gt;).&lt;/p&gt;
    &lt;p&gt;Although I'm not sure why someone would ever want to have over 64,000 lines of Delphi code in a single unit (a single file, for the non-Delphi developers out there), I was puzzled about the request. So I wrote a very large unit like that. Well, that's not entirely true, I wrote a program I used to write a large unit, with 20,000 functions for adding numbers (all with the same signature). Than I added the unit to the same program, called a function, and palced a breakpoint. In fact the developer asking the question was mentioning debugging problems. Here is the large unit in the debugger, stopped at line 81,732 (out of 120,011 lines):&lt;/p&gt;
    &lt;p style="text-align:center"&gt;
      &lt;img width="715" height="148" alt="" src="http://blog.marcocantu.com/images/forblog/bigunit.jpg"&gt;
    &lt;/p&gt;
    &lt;p&gt;I have not tried to compile and run the same application in Delphi 2007 (the version against which the problems was reported), but 2010 seems to handle it. Yes, opening the unit is not terribly fast, as the IDE has to parse it. As an experiment I tried to create and compile a unit with 200,000 similar functions, but the compiler started using the system memory and CPU at a very high rate and the compiled lines count after a while was moving versy slowly... so eventually I gave up compiling a unit with over a million lines of source code.&lt;/p&gt;
    &lt;p&gt;My original question remains, though. Why would one developer have such a large unit? Which are the largest units (in terms of lines of source code) you have?&lt;/p&gt;
    &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/v44mj3svm5mco3spnk45jgkjqk/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fblog.marcocantu.com%2Fblog%2Fhundred_thousand_lines_unit.html" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/marcocantublog/~4/yVEzQqUmnNE" height="1" width="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/489Wy0DUmdo" height="1" width="1"/&gt;</content><author><name>marcocantu</name></author><source gr:stream-id="feed/http://blog.marcocantu.com/blog_rss2.xmldata"><id>tag:google.com,2005:reader/feed/http://blog.marcocantu.com/blog_rss2.xmldata</id><title type="html">marcocantu.blog</title><link rel="alternate" href="http://blog.marcocantu.com/blog_rss2.xmldata" type="text/html" /></source><feedburner:origLink>http://feedproxy.google.com/~r/marcocantublog/~3/yVEzQqUmnNE/hundred_thousand_lines_unit.html</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1275982860425"><id gr:original-id="http://blog.marcocantu.com/blog/help_insight_xsl.html">tag:google.com,2005:reader/item/3574587ce0cf2941</id><title type="html">Delphi Help Insight XSL</title><published>2010-06-07T16:54:42Z</published><updated>2010-06-07T16:54:42Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/KXepHgJASUQ/help_insight_xsl.html" type="text/html" /><content xml:base="http://blog.marcocantu.com/blog_rss2.xmldata" type="html">&lt;p&gt;Over two past articles I focused on the &lt;a href="http://blog.marcocantu.com/blog/praise_help_insight.html"&gt;role of Help Insight&lt;/a&gt; and discussed &lt;a href="http://blog.marcocantu.com/blog/help_insight_customization.html"&gt;possible customizations&lt;/a&gt;. While researching for this last article, I tried changing the XSL file in the ObjRepos (object repository) folder of Delphi, with no effect. I had missed the fact the actual "live" files are in the language subfolder, in my case "en" for English. The right file to edit, on my computer, is:&lt;/p&gt;
    &lt;pre&gt;
C:\Program Files\Embarcadero\RAD Studio\7.0\ObjRepos\en\HelpInsight.xsl&lt;/pre&gt;
    &lt;p&gt;Here are some ideas to change the predefined XSL for Help Insight and get an extended output. In terms of actual information, the only that's not displayed is the full path of the unit containing the symbol definition. Notice also that the size of the output window depends on the content of the top &lt;em&gt;div&lt;/em&gt; called &lt;em&gt;main&lt;/em&gt;. &lt;/p&gt;
    &lt;p&gt;My extensions to the XSL are mostly at the end of the file, displayed below:&lt;/p&gt;
    &lt;p style="text-align:center"&gt;
      &lt;img width="871" height="332" alt="" src="http://blog.marcocantu.com/images/forblog/xsl_source.jpg"&gt;
    &lt;/p&gt;
    &lt;p style="text-align:left"&gt;The effect of the templates with mode &lt;em&gt;xmltohtml&lt;/em&gt; and attrotohml can be used to debug the data behind Help Insight, as they display a tree of the XML nodes in HTML, as for the &lt;em&gt;TButton&lt;/em&gt; symbol below:&lt;/p&gt;
    &lt;p style="text-align:center"&gt;
      &lt;img width="389" height="220" alt="" src="http://blog.marcocantu.com/images/forblog/hi_tbutton.jpg"&gt;
    &lt;/p&gt;
    &lt;p style="text-align:left"&gt;For local symbol you get much more information, including the full unit file name:&lt;/p&gt;
    &lt;p style="text-align:center"&gt;
      &lt;img width="633" height="288" alt="" src="http://blog.marcocantu.com/images/forblog/hi_method.jpg"&gt;
    &lt;/p&gt;
    &lt;p style="text-align:left"&gt;This is helpful to let you figure out the information behind Help Insight as you add comments. Finally the last template of the XSL file above makes a full copy of any comment portion enclosed in the HTML tag, letting you format the output freely, including any HTML tag including links (better to open them in a new page rather than in the Help Insight page). Below you can see the HTML in the comment, including a link to this blog, and the output below:&lt;/p&gt;
    &lt;p style="text-align:center"&gt;
      &lt;img width="733" height="299" alt="" src="http://blog.marcocantu.com/images/forblog/hi_method_html.jpg"&gt;
    &lt;/p&gt;
    &lt;p style="text-align:left"&gt;This is just the starting point of customizations you can do, and you can also change the CSS and the background image. The Help Insight pane opens up the ability to create fully customized viewers, driven by your source code and the comments you add to it. Demo XSL file download is &lt;a href="http://blog.marcocantu.com/images/forblog/HelpInsight.xsl"&gt;here&lt;/a&gt;.&lt;/p&gt;
    &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/v44mj3svm5mco3spnk45jgkjqk/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fblog.marcocantu.com%2Fblog%2Fhelp_insight_xsl.html" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/marcocantublog/~4/SzVT79K9w90" height="1" width="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/KXepHgJASUQ" height="1" width="1"/&gt;</content><author><name>marcocantu</name></author><source gr:stream-id="feed/http://blog.marcocantu.com/blog_rss2.xmldata"><id>tag:google.com,2005:reader/feed/http://blog.marcocantu.com/blog_rss2.xmldata</id><title type="html">marcocantu.blog</title><link rel="alternate" href="http://blog.marcocantu.com/blog_rss2.xmldata" type="text/html" /></source><feedburner:origLink>http://feedproxy.google.com/~r/marcocantublog/~3/SzVT79K9w90/help_insight_xsl.html</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1275382864538"><id gr:original-id="">tag:google.com,2005:reader/item/ab77a86a660292e5</id><title type="html">May 2010: Fun with the Windows 7 Taskbar</title><published>2010-05-29T15:42:22Z</published><updated>2010-05-29T15:42:22Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/9XS8XirjDH8/examinC5.htm" type="text/html" /><summary xml:base="http://www.drbob42.com/" type="html">In this article, I will show how we can manipulate the Windows 7 taskbar, and also how to solve an issue when running an application with the "run as Administrator" option while needing the taskbar to be able to send messages to it.&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/9XS8XirjDH8" height="1" width="1"/&gt;</summary><author><name>Bob@eBob42.com (Bob Swart)</name></author><source gr:stream-id="feed/http://www.drbob42.com/rss.xml"><id>tag:google.com,2005:reader/feed/http://www.drbob42.com/rss.xml</id><title type="html">Dr.Bob Examines...</title><link rel="alternate" href="http://www.drbob42.com" type="text/html" /></source><feedburner:origLink>http://www.drbob42.com/examines/examinC5.htm</feedburner:origLink></entry><entry gr:crawl-timestamp-msec="1274717984510"><id gr:original-id="">tag:google.com,2005:reader/item/7b4bf579719865e6</id><title type="html">Google Chrome Frame in your Delphi application « progdigy.com</title><published>2010-05-24T16:19:44Z</published><updated>2010-05-24T16:19:44Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/JamiesDelphiClippings/~3/KOiDPtm6_QQ/" type="text/html" /><link rel="related" href="http://www.progdigy.com/" title="www.progdigy.com" /><author gr:unknown-author="true"><name>(author unknown)</name></author><source gr:stream-id="user/07946391749317373099/source/com.google/link"><id>tag:google.com,2005:reader/user/07946391749317373099/source/com.google/link</id><title type="html">www.progdigy.com</title><link rel="alternate" href="http://www.progdigy.com/" type="text/html" /></source><summary type="html">&lt;img src="http://feeds.feedburner.com/~r/JamiesDelphiClippings/~4/KOiDPtm6_QQ" height="1" width="1"/&gt;</summary><feedburner:origLink>http://www.progdigy.com/?p=116</feedburner:origLink></entry></feed>

