Generics, records and typecasts = F2084 Internal Error: AV0DBFFBE9-R0000000C-0

Generics, records and typecasts = F2084 Internal Error: AV0DBFFBE9-R0000000C-0

// redux – not actual code

type

TKey = record

Index: Integer;

end;

TSomeClass = class abstract

procedure CopyTo(var Key: TKey); virtual; abstract;

procedure CopyFrom(var Key: TKey); virtual; abstract;

end;

TKeyValue = record

Key: TKey;

Value: T;

end;

TIndexList = TArray;

TKeyValueList = TArray<TKeyValue>;

TSomeClass = class(TSomeClass)

public type

TValueList = TArray;

private var

ValueList: TValueList;

procedure CopyTo(var Key: TKey); override;

procedure CopyFrom(var Key: TKey); override;

end;

procedure TSomeClass .CopyTo(var Key: TKey);

begin

TKeyValue(Key).Value := ValueList[Key.Index]; // OK

end;

procedure TSomeClass .CopyFrom(var Key: TKey);

begin

ValueList[Key.Index] := TKeyValue(Key).Value; // F2084 Internal Error: AV0DBFFBE9-R0000000C-0

end;

CopyTo/From called with a list of TKeyValue params.

I guess I was asking for it. Rewrote to use regular class objects.

11 thoughts on “Generics, records and typecasts = F2084 Internal Error: AV0DBFFBE9-R0000000C-0


  1. Dorin Duminica It is amazing how much scaffolding code clutter you can remove with it. Working on a wrapper for grids that allows me to completely forget about configuring the grid settings. All data typesafe, populated from a class list, or from an SQL query.


    We have a LOT of grids, all with similar event handlers, refresh needs, sorting, grouping, sizing and scaling, look and feel, copy to clipboard, etc. I now define a non-visual grid with the right types, and hook up with a visualizer that I hook up to a grid component.


    It removes hundreds of lines of grid handling per grid in a form, and replaces it with a few dozen lines of declaration and a few lines of implementation.


    http://pastebin.com/q2Gkq5Pn


    Visual result (right side grid)


    https://drive.google.com/open?id=0B1MyXorVzay9UGVRQWpwdWRvOEk


  2. that looks really good!!


    I once wrote a lib < 1.5KLOC that handled everything from generating database to advanced queries in Delphi with basic generics and attributes; whenever I tried something smart with generics, I'd get some cryptic errors just like you, so, I gave up on anything generic that seemed that no one would write test case for, shame really…


  3. My own use of generics has so far been light, but I wrote some very useful generic array code, and as you say, Lars, it helped me remove a good deal of clutter from mainline code. But it also let me condition array access to avoid range error issue, among other things.


    Since I am working in both D2007 and XE7, I am limited in what I can do, but as we shift more and more to XE7, I expect that generics will play an increasing role.


  4. No problem here on Seattle with some minor changes


    unit Unit1;


    interface


    type


    TKey = record


    Index: Integer;


    end;


    TSomeClass = class abstract


    procedure CopyTo( var Key: TKey ); virtual; abstract;


    procedure CopyFrom( var Key: TKey ); virtual; abstract;


    end;


    TKeyValue = record


    Key: TKey;


    Value: T;


    class operator explicit( const Key: TKey ): TKeyValue;


    end;


    TIndexList = TArray;


    // TKeyValueList = TArray<TKeyValue>;


    TSomeClass = class( TSomeClass )


    public type


    TValueList = TArray;


    private


    var


    ValueList: TValueList;


    procedure CopyTo( var Key: TKey ); override;


    procedure CopyFrom( var Key: TKey ); override;


    end;


    implementation


    procedure TSomeClass.CopyTo( var Key: TKey );


    var


    lval : TKeyValue;


    begin


    lVal := TKeyValue(Key);


    lVal.Value := ValueList[ Key.Index ]; // OK


    end;


    procedure TSomeClass.CopyFrom( var Key: TKey );


    begin


    ValueList[ Key.Index ] := TKeyValue( Key ).Value;


    end;


    { TKeyValue }


    class operator TKeyValue.explicit( const Key: TKey ): TKeyValue;


    begin


    Result.Key := Key;


    Result.Value := default ( T );


    end;


    end.


  5. Oliver Münzberg  The external methods don’t need the Value. They only work with the Index. Interesting trick with the explicit operator!


    Anyways – the regular object code became much cleaner and shorter than the record overloaded version.


    Developing new classes is interesting. You sometimes have to go a few iterations before their final form appear.


    Usually, you know you are on the right track when you start deleting code that is no longer needed.


  6. FYI, the actual code lifts the following from the grid


    Top Row


    Current Row


    Selected Rows


    Checked Rows


    before an update, and then tries to restore the values to the grid after the update, checking if the value:T at the index still matches, and if not – searches out the row that matches.


  7. Lars Fosdal It sounds very cool, would be glad if you could share it when you get it done. Setting up the grids takes more time than the actual code for the whole form.


  8. Attila Kovacs It is still not at a maturity where it is ready for others to use. Also – I need to get permission from my employer.


    If I eventually make it available, you will find out in this forum.

Leave a Reply