Stefan Glienke 2002 Posted July 14, 2020 2 hours ago, Kas Ob. said: wonder if there is trick(s) to make this works No - Anything is an untyped var parameter - if you put such a signature into an interface with methodinfo on you even get a funky compiler error E2134 Type '<void>' has no type info Share this post Link to post
Remy Lebeau 1393 Posted July 14, 2020 7 hours ago, Kas Ob. said: I wonder if there is trick(s) to make this works Not the way you have shown, no. All type info is lost with an untyped var parameter, so you HAVE to specify a type somehow. A Generic is the most direct way to specify a type in a, well, generic manner, eg: type TRecSI = record FInteger: Integer; FString: string; constructor Create(const s: string; i: Integer); end; THelper = class class procedure DoSomething<T>(var Anything: T); end; constructor TRecSI.Create(const s: string; i: Integer); begin FInteger := i; FString := s; end; class procedure THelper.DoSomething<T>(var Anything: T); begin case GetTypeKind(T) of tkInteger: Writeln(PInteger(@Anything)^); /// end; end; var A: Integer; B: string; C: TArray<Byte>; D: TArray<Integer>; E: TArray<string>; F: TRecSI; begin THelper.DoSomething(A); THelper.DoSomething(B); THelper.DoSomething(C); THelper.DoSomething(D); THelper.DoSomething(E); F := TRecSI.Create('Hello', 1234); DoSomething(F); Readln; end. Otherwise, you could use TValue instead, eg: type TRecSI = record FInteger: Integer; FString: string; constructor Create(const s: string; i: Integer); end; constructor TRecSI.Create(const s: string; i: Integer); begin FInteger := i; FString := s; end; procedure DoSomething(const Anything: TValue); begin case Anything.Kind of tkInteger: Writeln(Anything.AsInteger { or: Anything.AsType<Integer> } ); /// end; end; var A: Integer; B: string; C: TArray<Byte>; D: TArray<Integer>; E: TArray<string>; begin // TValue supports implicit conversions for some fundamental types... DoSomething(A { or: TValue.From(A) }); DoSomething(B { or: TValue.From(B) }); // but no implicit conversions for array types... DoSomething(TValue.From(C)); DoSomething(TValue.From(D)); DoSomething(TValue.From(E)); // or records... DoSomething(TValue.From(TRecSI.Create('Hello', 1234))); Readln; end. Share this post Link to post
Stefan Glienke 2002 Posted July 14, 2020 17 minutes ago, Remy Lebeau said: TValue supports implicit conversions for some fundamental types but no implicit conversions for array types or records... If we just could write class operator Implicit<T>(const value: T): TValue; ... oh wait... we can! type TValueHelper = record helper for TValue class function &&op_Implicit<T>(const value: T): TValue; static; end; class function TValueHelper.&&op_Implicit<T>(const value: T): TValue; begin TValue.Make(@value, System.TypeInfo(T), Result); end; 2 Share this post Link to post
Mahdi Safsafi 225 Posted July 14, 2020 (edited) 1 hour ago, Stefan Glienke said: If we just could write class operator Implicit<T>(const value: T): TValue; ... oh wait... we can! type TValueHelper = record helper for TValue class function &&op_Implicit<T>(const value: T): TValue; static; end; class function TValueHelper.&&op_Implicit<T>(const value: T): TValue; begin TValue.Make(@value, System.TypeInfo(T), Result); end; Very excellent Stefan ! Just noticed that the new operand overrides the original one for integer-literal : DoSomething(1); // calls yours operand. DoSomething(a); // calls default operand. a=integer. DoSomething('test'); // calls default operand. DoSomething(str); // calls default operand. str=string. EDIT: I guess the answer is here: class operator TValue.Implicit(Value: Integer): TValue; Edited July 14, 2020 by Mahdi Safsafi Share this post Link to post
Stefan Glienke 2002 Posted July 14, 2020 54 minutes ago, Mahdi Safsafi said: Just noticed that the new operand overrides the original one for integer-literal Yes, because 1 is not Integer Share this post Link to post
aehimself 396 Posted July 14, 2020 21 hours ago, PeterPanettone said: However, your employer has to pay for the time you need to write overloaded code. (Though I assume you're a fast writer). These overloaded methods are like 4 lines. I really would like to have an employer who pays me double for 4 extra lines per feature request. In a real world scenario, overloaded methods usually point from one to the other (or call the "real" one with proper adjustments) so we can argue that this was for demonstration only, but in real life - multiple overloaded methods will not consume even 10 minutes of your time if done smartly. Share this post Link to post
Fr0sT.Brutal 900 Posted July 24, 2020 (edited) United types are a headache in JS/TS... you must always check whether that 'foo' is number, or string, or maybe string object, or undefined, or null... Overloaded methods rule. Compiler takes care of correct branching so you can't forget some type check and ruin your app. One addition I'd add to generics is "is" operator for simple types. Nevertheless, "de-generising" a type is a bad practice that should be avoided so I doubt is would be added to language Edited July 24, 2020 by Fr0sT.Brutal Share this post Link to post