Delphi Constraints in Generics – RAD Studio XE documentation wiki
Posted by jpluimers on 2011/04/21
Quite a few things are similar when doing Generics in both Delphi and C#.
But constraints are a bit different.
To quote the Delphi Wiki page on Constraints in Generics – RAD Studio XE:
Constraints can be associated with a type parameter of a generic. Constraints declare items that must be supported by any particular type passed to that parameter in a construction of the generic type
Constraint items include:
- Zero, one, or multiple interface types
- Zero or one class type
- The reserved word “constructor“, “class“, or “record“
You can specify both “constructor” and “class” for a constraint. However, “record” cannot be combined with other reserved words.
Multiple constraints act as an additive union (“AND” logic).
A few other differences are these:
- In .NET, there is a unified typing system: everything descends from System.Object, including both value types and reference types. In Delphi this is not the case. In .NET, when you don’t specify a constraint, but use the type in a reference way, it will do automatic boxing. Delphi has no concept of automatic boxing, so you cannot use a non-constrained type as a reference
- In both .NET and Delphi, you cannot specify a constraint on an enumeration type. In .NET you can work around this by constraining on the underlying interfaces. In Delphi you cannot do that because enumeration types are ordinal types that do not implement interfaces.
- In Delphi you cannot constrain on ordinal types.
Note that – like the Delphi documentation – the C# constraints on type parameters documentation is not complete on those either.
Related: a great post [WayBack] Using Generics in Delphi – Phil Gilmore covering the comparison between C# and Delphi in more depth.
–jeroen
Delphi “Variant Records”, a few notes « The Wiert Corner – irregular stream of stuff said
[…] think you can create a generic record as long as you apply a record constraint on the generic […]
Impossible: Property using Generics in Delphi. Interfaces/classes/methods/fields/constraints/type inferencing are « The Wiert Corner – irregular stream of stuff said
[…] Generic constraints (a bit buggy in Delphi 2009) […]
Lars Fosdal said
What annoys me, is that I cannot limit the type to be f.x. a number, an enumerable, or a set.
Lars Fosdal said
Drat… I forgot to change the < to <
They should read:
TMyComplexType<TA, TB:TMyType> = …
TMyComplexType<TB:TMyType; TA> = …
Lars Fosdal said
Delphi XE allows for constructs like
type
TMyControlList<T:TWinControl> = class(TList<T>);
TMyObjectList<T:TMyObject, constructor> = class(TList<T>);
Another challenge is multityped generics with/without constraints.
type
TMyComplexType = …
cause both TA and TB to be constrained to TSomeType.
If I want TA to be unconstrained, I have to put it like
type
TMyComplexType = …
This can be awkward for the logic of the parameter ordering (ie you would have expected to have TA as the first param).
Alistair Ward said
I don’t have XE on hand to try, but I had a bad experience with constraints in D2010.
Watch out for the “class” constraint – it actually constrains the type to a reference type (either a class OR an interface). The problem is that if you want to constrain a type to really be a class (ie TObject) you can’t, as (at least in D2010) the compiler issues an error if you try to use TObject as a constraint and tells you to use “class” instead!
Chris said
“But constraints are a bit different”
In what way? (Genuine question…) They seem pretty much a copy of C# 2/3’s to me, slightly different syntax aside, right down to the things that don’t make much sense in Delphi (‘class’ instead of ‘TObject’ [Object], ‘record’ [struct] for any value type, and the nature of the constructor constraint).
jpluimers said
Alistair Ward commented an important difference. Another issue will be in the article soon: enums
–jeroen
Chris said
‘Alistair Ward commented an important difference.’
You sure? The ‘class’ constraint in C# allows for interface types too, and as I said, you can’t constrain to Object in C#, just like you can’t constrain to TObject in Delphi – you have to use ‘class’.
jpluimers said
I stand corrected: you taught me something new on C# today :)