Posts tagged .NET

DeHL 0.8.2 is out

DeHL

I’ve just released the version 0.8.2 of DeHL. The downloads can be found on this page and changelog on this page.
Again, this is a minor release with a few bugs fixed and a new feature: TString (as asked in this comment).
As you might have guessed already, TString is a wrapper record modeled on .NET’s System.String class. Unfortunately I was unable to use most of the RTL’s string functionality so the “wrapper” grew quite a bit from my original expectations.

But … enough talk, here are some usage scenarios that someone may find useful:

var
  LStr: TString;
begin
  { Overloaded operators and a special function "U" }
  LStr := U('Hello World for the ') + 10 + 'th time!';

  { Do some random operations }
  if (LStr.ToUpper().Contains('HELLO')) and
     (LStr.Contains('HeLLo', scLocaleIgnoreCase)) then
  WriteLn(LStr.ToString);

  { Now let's select all the distinct chars from the string }
  WriteLn(
    LStr.Concat(LStr.AsCollection.Distinct.Op.Cast<string>).ToString
  );
end.

TString overloads all sane operators: Equality, Inequality, Implicit conversions, Addition, Subtraction and offers functions to convert to and from UTF8 and UCS4 (via RTL of course). I also need to iron a few things about about Enex integration for the next minor release.

The other small improvement that I added relates to the collection package. All simple collections (not the Key/Value pair ones) implement a sort of “where T is the_class, select it as such” operation. Check out this example:

var
  LList: TList<TObject>;
  LBuilder: TStringBuilder;
  LObject: TObject;
begin
  LList := TList<TObject>.Create;

  { Populate the list with some random objects }
  LList.Add(TInterfacedObject.Create);
  LList.Add(TStringBuilder.Create);
  LList.Add(TStringBuilder.Create);
  LList.Add(TObject.Create);

  { Now select the objects we're interested in (string builders) }
  for LBuilder in LList.Op.Select<TStringBuilder> do
    WriteLn(LBuilder.ClassName); // Do stuff

  { Or select everything (not actually required - an example) }
  for LObject in LList.Op.Select<TObject> do
    WriteLn(LObject.ClassName); // Do stuff
end.

If it’s still not clear what this operations does, let me explain. It basically consists of two operations: Where and Select. First, each object is checked to be of a given class and then this object is cast to that class so you can iterate directly using a FOR .. IN loop only over the objects you want to. Of course doing that for TObject makes no sense (as in example) … but well … that was an example.

Well, that’s all for today,
Have Fun!

Delphi Prism: DelphiString

Was just reading the source code for ShineOn (the RTL implementation in Delphi Prism) and found an interesting piece: DelphiString (in /ShineOn.RTL/DelphiString.pas).

What is it? It is a class that tries to replicate the behavior of the Win32 Delphi’s String type.The difference between Delphi’s String and .NET string is that the first one is mutable (aka can be written to but not thread-safe) and the second is immutable (can’t be modified making it thread-safe but harder to use).

If you are porting an application over Win32 Delphi you can’t normally use .NET’s String class because most of your code surely makes operations on strings.

Back to DelphiString; you might be tempted to use it simply by replacing all instances of String with DelphiString in your code — WRONG! Because Win32 Delphi uses a technique called Copy-On-Write, code like this:

S1 := 'John'
S2 := S1;
S2[1] := '_';
ASSERT((S1= 'John') and (S2 = '_ohn'));

… will work as expected (in Win32 Delphi) even if S2 is initially pointing to the same string as S1! In Delphi Prism, S2 will point to the same object as S2, but no “copy-on-write” will be performed and both strings will eventually be changed to “_ohn”. A simple “replace all String with DelphiString” will not be enough. I would kindly suggest that the application gets ported to use .NET String class rather than DelphiString.

Overridden method should match case of ancestor

I’ve been following CodeRage III these days and presenter mentioned that in Delphi 7 (and above), when overriding virtual methods, the same case should be used for both functions.

Consider this example:

type
  TClass1 = class
    procedure VirtualMethod; virtual; abstract;
  end;

  TClass2 = class(TClass1)
    procedure virtualmethod; override;
  end;

procedure TClass2.virtualmethod;
begin
end;

In this case indeed the compiler will issue this warning:

[DCC Hint] Project2.dpr(14): H2365 Override method TClass2.virtualmethod should match case of ancestor TClass1.VirtualMethod

Why is the case important? Delphi is case-insensitive. Considering that this change came from Delphi 7 we can assume it was related to “preparations for .NET”. Considering that .NET IL is case-sensitive (in case of identifiers) this warning makes sense if you’re trying to extend some .NET class. Now that Delphi.NET is dead, maybe the compiler team will clean up this mess a bit.

New C#: Exactly my point!

I was debating some of the new flashy changes planned for new C# version with some of my colleagues … It seems no matter what Microsoft does it’s always considered as an in innovation in the field. Let’s check out the new proposed feature “dynamic”: Dynamic would allow you C# program to inter-operate with external scripts and much more. It’s marketed as the new big thing for C# and would allow for much greater flexibility.

But wait! I think I’ve seen something like this before … way before 2008 – oh yeah it was mid-’90s when I’ve tried Delphi 5! The feature was called Variant. Delphi language included dynamic dispatching (in form of IDispatch) from the 3rd version. Since then It has evolved the feature to allow for much more complex use cases. And I think Delphi wasn’t even the first one to introduce such a concept directly into the language – it was VB (but I may be wrong on this one).

Oh, and now for the title of my post – Exactly my point!

Instantiating Generic Types at runtime

When working on my license project, I came across an uncommon case in C# where I would have to create an instance of a generic type (wich had multiple type parameters) dynamically.

Basically I had an instance of Dispatcher<A, B, C> that would be created with different type parameters A, B and C depending on the user’s selection. A and B were in my case classes of type ILoadBalancer and C a IScriptAssembler.

In order to avoid 3×3 Ifs in the code (which is actually quite dumb) I had to:

  1. Extract an simple (not generic) interface IDispatcher from Dispatcher<A, B, C> class.
  2. Instantiate the generic class at runtime:
    Type dynamicDispatcher = typeof(Dispatcher<,,>).MakeGenericType(
        new Type[] {typeof(CSharpScriptAssembler), userLocalBalancer, 
            userRemoteBalancer }
    );
    
  3. Create a new instance of the newly generated non-generic type:
    m_Dispatcher = (IDispatcher)Activator.CreateInstance(
        dynamicDispatcher,
        new Object[] { userQueueSize, userNumberOfThreads, mode }
    );
    

So, as you can see, we have to first create a non-generic type out of the generic one at runtime. And then use the Activator singleton to actually create a new instance of that type.

Points of interest:

  1. Type.MakeGenericType()
  2. Activator.CreateInstance()