aehimself 396 Posted January 20, 2020 Hello all, I'm implementing a custom typed class, e.g.: TMyClass<T> = Class strict protected list: TDictionary<String, T>; public Function Get(Identifier: String): T; End; Function TMyClass<T>.Get(Identifier: String): T; Begin If list.ContainsKey(Identifier) Then Result := list[Identifier] Else Result := ???; End; Question is simple. Is there a default null value for T which I can substitute ??? with? For Strings, it should return '', for numerical values 0, for classes nil and so on. Thanks! Share this post Link to post
Dalija Prasnikar 1396 Posted January 20, 2020 Yes, there is. Result :=Default(T); 1 Share this post Link to post
David Heffernan 2345 Posted January 20, 2020 System.Default(), still not documented I think Share this post Link to post
aehimself 396 Posted January 20, 2020 @Dalija Prasnikar Nice, thank you! Exactly what I was looking for 🙂 Just out of curiosity, where it is declared? It says System, but I can not see the implementation. I like to see what I am using 🙂 Share this post Link to post
Stefan Glienke 2002 Posted January 20, 2020 It's a "magic" function implemented by the compiler without code in System.pas Share this post Link to post
aehimself 396 Posted January 20, 2020 Is it possible to learn this power? 🙂 To make functions without code? 🙂 Share this post Link to post
Stefan Glienke 2002 Posted January 20, 2020 Sure, write your own compiler 1 5 Share this post Link to post
Remy Lebeau 1393 Posted January 20, 2020 (edited) Default() is a compiler intrinsic function, it is built right in to the compiler itself. That being said, I would suggest some tweaks to your code. There is no need to search for the key twice, that is just wasted overhead. Use the TryGetValue() method instead, which searches the key once and returns its value if found: Function TMyClass<T>.Get(Identifier: String): T; Begin If not list.TryGetValue(Identifier, Result) Then Result := Default(T); End; Alternatively, TryGetValue() sets the output value to Default(T) for you if the key is not found, so you don't need to do it explicitly at all: Function TMyClass<T>.Get(Identifier: String): T; Begin list.TryGetValue(Identifier, Result); End; But either way, this approach does not allow the caller to differentiate between a key that is actually missing vs a key that happens to have the same value as its default. So I would suggest returning a Boolean instead to tell the caller whether the key was found or not: TMyClass<T> = Class strict protected list: TDictionary<String, T>; public Function Get(Identifier: String, out Value: T): Boolean; End; Function TMyClass<T>.Get(Identifier: String; out Value: T) Boolean; Begin Result := list.TryGetValue(Identifier, Value); End; Edited January 21, 2020 by Remy Lebeau 1 Share this post Link to post
Lars Fosdal 1792 Posted January 21, 2020 This is going to get interesting if we get nullable generic types. Share this post Link to post
David Heffernan 2345 Posted January 21, 2020 2 hours ago, Lars Fosdal said: This is going to get interesting if we get nullable generic types. Why? You mean the choice between nil and Default(T) as the result of Default(Nullable<T>)? In C# the default value is nil. Share this post Link to post
Lars Fosdal 1792 Posted January 21, 2020 TRec<T> = record value: T; procedure Init; end; procedure TRec<T>.Init; begin Value := Default(T); end; TRec<Integer> = record value: Integer; // Default(T) = 0 end; TRec<TObject) = record value: TObject; // Default(T) = NIL end; // Assuming nullables would look like the C# equivalents TRec<Integer?> = record value: Integer?; // Default(T) = NULL end; TRec<TObject?) = record value: TObject?; // Default(T) = NULL end; For nullable object references - will we have a non-NULL that is nil? I guess the C# solution makes sense, although there is a difference between NULL (never assigned) and nil ( known non-reference assigned). Share this post Link to post
Stefan Glienke 2002 Posted January 21, 2020 (edited) In C# there is no Nullable<T> where T is a reference type (because the declaration is like this: public struct Nullable<T> where T : struct) unless you are using C# 8 and have enabled nullable reference types - and then there still is no Nullable<T> for any T that is not a struct but the compiler prevents null in a reference type unless you specify it as nullable. I am pretty much sure that if we ever get nullables in Delphi they don't implement such a feature as C# 8 does to prevent null/nil in reference types. Edited January 21, 2020 by Stefan Glienke 1 Share this post Link to post
Tommi Prami 130 Posted January 22, 2020 On 1/20/2020 at 9:52 AM, Dalija Prasnikar said: Yes, there is. Result :=Default(T); Thanks! I jumped through some serious hoops to get that. Have to go through that code... Share this post Link to post