Considering that we now can have constants within records and classes –

Considering that we now can have constants within records and classes –

why can’t we have resource strings in there?

type

TMyRec = record

const

ThisIsOK = ‘String’;

resourcestring <- [dcc32 Error] : E2029

ThisIsNotOK = ‘string’;

end;

[dcc32 Error] : E2029 ‘END’ expected but ‘RESOURCESTRING’ found

33 thoughts on “Considering that we now can have constants within records and classes –


  1. Jeroen Wiert Pluimers But resourcestring naming can’t be global?


    unit A;


    interface


    resourcestring


    ResName = ‘name’;




    unit B;


    interface


    resourcestring


    ResName = ‘lastname’;


    How are they named globally?


    AFAIK, you can also have resource strings in the implementation section of a unit?


  2. The resource string is not a constant. It can vary in different translations.


    Initialized variables in records and classes would be an interesting addition.


    TMyRec = record


    MyField: Integer = 111;


    end;


  3. T n T It is a constant from a compilation perspective, but it is correct that it’s returned value can be changed with the translation tools at run time.


  4. Jeff Dyer It would not be the same constant. The constants would be tied to a specific context, so that constants that happens to have similar or even identical names, could co-exist without namespace pollution


  5. David Heffernan If all records of type Tx have the same constant in them , that adds no information to the system, as far as I can see. We can surely infer the type of the record using “if X is Tx”, and the constant can’t help us identify individual records, so I don’t see what the point of this is at all.


  6. Paul TOTH AFAIK the point of resource strings is to be able to build different versions of the application for different installations, for example multi language or different clients without resorting to configuration files. Those are the only times I’ve used them.


  7. Jeff Dyer Translation is the reason we do it as well. However, we have a large number of UI screens, and texts and terms can be similar but not necessarily identical in all contexts – hence using the same translation is at times completely wrong.


    Like for any other type / const / variable scoping – it would be beneficial to be able to limit the scope of a resourcestring so that it is only accessible with the scope that it belongs to.


  8. Why don’t you just isolate like I showed yesterday, I don’t think there is a better solution or ever will be. Records are not made to represent a namespace.


  9. Jeff Dyer In general, yes. However, when the presentation strings are fed as attributes to a generic class which purpose is to hold, sort, filter and format SQL query data specific to a presentation, and that is fed to an empty grid at runtime through a TGridView class which adapts the data to the specific grid type, we are in the presentation layer, not the business logic layer.


    TOrderGridSet = class(TGridSet)


    public


    [GridAutoSize]


    [InitField(‘Batch’, 60),Autosize]


    SchoolClass: TGridSet.TFieldString;


    [InitField(‘Date, 90),Autosize]


    ConsumptionDate: TGridSet.TFieldDate;


    [InitField(‘Client’, 60),Autosize]


    ConsumerName: TGridSet.TFieldString;




  10. Anyways – that “smell” thing is not the question here. The question is if there is any logical reason in the compiler for not allowing “private” resourcestring declarations.


  11. Jeff Dyer I’m not making any comment on how Lars Fosdal chooses to design his code. I’m explaining to you why you would declare constants inside compound types like records or classes.


  12. Lars Fosdal While technically possible, this is not a primary concern in Delphi. The unit is a namespace. If you need two different resource strings with the same name, you may need to split your unit into two ones.


  13. T n T – If you split it into two units that means you introduce a unit sequence dependency since the last unit in scope is the one providing the value you refer to, and you don’t get any hint or warning informing you that there is a namespace clash.


  14. Lars Fosdal you can prefix the name with the unit name to ensure that there’s no collision.


    my first impression with class method or class const and type was that it is not necessary because namespace are handled by units.


    now I use them sometime to avoid splitting my code into several units 🙂


  15. Paul TOTH I use class internal types and constants all the time.


    Not only does it make scoping crystal clear – it also prevents OOP inheritance abuse, since the internal classes can’t readily be hijacked for something they wasn’t intended for.


    I often do stuff like this


    TMyDBClass = class(TDBObject)


    type


    fn = record const


    view = ‘v_MyDBTableView’;


    field1= ‘field1’;


    field2 = ‘field2’;


    end;


    private


    FField1: string;


    FField2: string;


    public


    property Field1 read FField1 write FField1;


    property Field2 read FField2 write FField2;


    end;


    so that I can stuff like


    sql = QBuilder.Select([fn.field1, fn.Field2]).From(fn.view);


    and do


    Field1 := recset.FieldByName[fn.field1].AsString;


    to make sure that all my field references are not simply multiple string constants, but one single constant. Makes it trivial to refactor field names and to avoid the accidentally misspelled field name in FieldByName[‘filed1’].


  16. Lars Fosdal I do the same


    TCustomer = record


    CONST


    TABLE_NAME = ‘Customers’;


    KEY_FIELD = ‘Id’;


    public


    Name: string; // I miss the [size] suffix for Unicode string


    !


    Birth: TDateTime;

Leave a Reply