Problems with Delphi code migration

I had a problem between Delphi 2010 and Delphi Berlin (last update) during my code migration .... I made simple code to demonstrate weird behavior ...

I have an application that uses TList (first) and TList (from Generics.Collections). I know that this code snippet (below) does not make any sense to you, but it is for demonstration purposes.

unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TTest = class Name: string; constructor Create(Nome: string); end; TForm1 = class(TForm) btn1: TButton; procedure btn1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private FList: TList; end; var Form1: TForm1; implementation uses System.Generics.Collections; {$R *.dfm} procedure TForm1.btn1Click(Sender: TObject); var tmpList: TList<TTest>; begin tmpList := TList<TTest>.Create; tmpList.Add(TTest.Create('A')); tmpList.Add(TTest.Create('B')); tmpList.Add(TTest.Create('C')); tmpList.Add(TTest.Create('D')); tmpList.Add(TTest.Create('E')); FList := TList(tmpList); ShowMessage(TTest(FList[0]).Name); end; procedure TForm1.FormCreate(Sender: TObject); begin FList := TList.Create; end; constructor TTest.Create(Nome: string); begin Name := Nome; end; end. 

In Delphi 2010, ShowMessage shows a β€œA”, but in Delphi Berlin it causes an Acess violation

Both optimized apps set to False

+5
source share
2 answers
 FList := TList(tmpList); 

This is problem. The cast is simply incorrect because tmpList not a TList .

Your code is compiled only because of the throw, but casting does not change the fact that the object on the right side is not of the type that is being done. All throws do not allow the compiler to complain and save you from yourself. Your throw is a lie to the compiler, and a runtime error is the result.

This code may have worked in older versions, but only by accident. Your luck has changed.

It is hard to know what to offer for correction. As you say, the code makes little sense. Each time you click the button, you skip the list. I suggest deleting all videos, stop using non-Generic TList and use only shared lists.

+8
source

The TList<T> is independent of / t TList .

You cannot drop one on TForm other and expect reasonable results more than you could use TForm to TButton (for example).

In Delphi, tricks like this form are not marked, sometimes called hard-casting. That is, the compiler will simply trust that you know what you are doing and will just match, but if the type is invalid, the results will be unpredictable.

For conversions between types of reference objects (and / or links to an interface), you can use a verified listing using an operator like :

 FList := tmpList as TList; 

If the checked listing is invalid (for example, this one), then the compiler will throw an exception at runtime, warning you of an error.

Why does the compiler even allow unverified casts?

In some cases, uncontrolled castings can be useful and safely used in specific applications. But outside these specific conditions, uncontrolled passages at best trust luck or specific compiler behaviors or RTL characteristics that can be changed.

eg. A 32-bit trick of storing object references or other pointer values ​​in an Integer variable. Such code may continue to work upon recompilation for the 64-bit version, but now only in case of luck and only in some cases, since only a subset of the possible 64-bit pointer values ​​can be safely stored in the 32-bit Integer.

If you have code that successfully compresses between TList and TList<T> , then it worked only luck, as a result of some specific compiler or RTL behavior at this time.

+6
source

Source: https://habr.com/ru/post/1269994/


All Articles