Delphi 10.4 Sydney の ARC 廃止ついて

# Delphi 10.4 Sydney リリース

待望の [Delphi 10.4 Sydney](https://www.embarcadero.com/jp/products/rad-studio/whats-new-in-10-4-sydney) が発表されましたね！
（Community Edition はライセンス違反の商用使用が多いためリリース時期を遅らすそうです）

この記事ではメモリ管理モデルの変更である ARC の廃止について見ていきます。

ちなみに、同時に導入された Managed Record によって**スマートポインタが実装できる**ようになったので、ARC が必要だった場合でも問題無いですね！これについては、また今度。

# ARC 廃止

Delphi がモバイルコンパイラを搭載してから ARC (Automatic Reference Counting: 参照カウンタ)によるメモリ管理がサポートされてきました。
しかし、Delphi ユーザーは元々 ARC を積極的に使っていなかった＆コンパイラが複雑になる問題があったため、まず Linux 版コンパイラで、そして 10.4 では全てのコンパイラで ARC が廃止されました。

```pascal:ARCの実例
procedure ARC;
begin
  var Foo := TFoo.Create; 
  Foo.Bar; 
end; // ARC がサポートされていると、ここで Foo は解放される
```

Delphi 使いの方々は ARC を使わず try-finally ブロックで書いてましたよね。

```pascal:ARCに頼らない書き方
procedure ARC;
begin
  var Foo := TFoo.Create; 
  try
    Foo.Bar; 
  finally
    Foo.Free;
  end;
end; 
```

ということで、この ARC の廃止で気になるトピックを 5 つほど紹介します。

## 1.ARC 廃止で TInterfacedObject は影響を受けない

タイトルで言いたいことを書きましたが、そういうことです。
以前 Linux 版の時にも書きましたが、皆が心配しているみたいなので。

[DocWiki](http://docwiki.embarcadero.com/RADStudio/Sydney/ja/%E6%96%B0%E6%A9%9F%E8%83%BD#.E3.83.A1.E3.83.A2.E3.83.AA.E7.AE.A1.E7.90.86.E3.81.AE.E7.B5.B1.E5.90.88) にも書いてありますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/26dd3b58-0d5d-009d-7752-8035d339240c.png)



```pascal:TInterfacedObjectは問題ない
type
  IFoo = interface
    procedure Hello;
  end;

  TFoo = class(TInterfacedObject, IFoo) // TInterfacedObject による参照カウンタを使う
  public
    procedure Hello;
  end;

procedure Bar;
begin
  var Foo: IFoo := TFoo.Create; // 型が IFoo になっていることに注意。
  Foo.Hello;                    // TInterfacedObject の Interface は今まで通り自動開放される
end;
```

## 2.ARC 廃止でモバイルプラットフォームでも AnsiString が使える

ARC 廃止に伴って AnsiString が全プラットフォームで使えるようになりました。
以下のコードをモバイル向けにコンパイルしようとすると 10.3 ではエラーになりますが、10.4 ではエラーになりません。

```pascal:AnsiStringが使える
var
  Ansi: AnsiString; // 10.3 ではここでエラー, 10.4 は OK
begin
  Ansi := 'Hello ?';
  Writeln(Ansi);
  Readln;
end.
```

つまり、10.4 では [TMarshall](http://docwiki.embarcadero.com/Libraries/Sydney/ja/System.TMarshal) や、[TMarshaller](http://docwiki.embarcadero.com/Libraries/Sydney/ja/System.SysUtils.TMarshaller) を使ったりしなくて良くなりました。

```pascal:10.4ではAnsiStringのためにMashallerを使わなくて良い
var
  M: TMarshaller;
begin
  var P := M.AsAnsi('Hello ?').ToPointer;
  // Ansi文字列の処理を P に対して行う
end;
```

## 3.ARC 廃止で文字列のインデックスがまた変わった

おわー！？！？！？
ということで、ARC 廃止によって全コンパイラの文字列のインデックスが**元に戻りました**！
つまり、Android や iOS でも、文字の先頭インデックスは **1** です！
ただし、**[TStringHelper.Chars](http://docwiki.embarcadero.com/Libraries/Sydney/ja/System.SysUtils.TStringHelper.Chars) は 0 インデックスのまま**です。

```pascal:モバイルコンパイラでもインデックスは１
procedure TForm1.Button1Click(Sender: TObject);
begin
  var Str := 'Hello, Delphi 10.4!';
  Edit1.Text := Str[1];      // 10.4 では 'H' が返るが 10.3 では 'e' が返る
  Edit1.Text := Str.Chars[0] // 10.4 でも 10.3 でも 'H' が返る
end;
```

マイグレーションが楽になったりする…かも？
まあ、でも TStringHelper.Chars を使った方がいいのかな…？

## 4.DisposeOf の立場が無くなる

ARC が廃止されたため、DisposeOf を使わず Free で済むようになりました。

## 5.Weak 参照の立場が無くなる

こちらも ARC が無くなったので、最早参照カウントの増加もおきず、この Attribute は ARC に対しては必要無くなりました(Interface に対しては未だに有効です)。

## 6.AUTOREFCOUNT, NEXTGEN が未定義に

当然ですが [AUTOREFCOUNT](http://docwiki.embarcadero.com/RADStudio/Sydney/ja/Delphi_%E3%83%A2%E3%83%90%E3%82%A4%E3%83%AB_%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E3%81%A7%E3%81%AE%E8%87%AA%E5%8B%95%E5%8F%82%E7%85%A7%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88#ARC_.E3.81.A8_.7B.24AUTOREFCOUNT.7D_.E6.8C.87.E4.BB.A4) も未定義になりました。
そして、NEXTGEN も未定義になりました。

Delphi 10.4 Sydney の定義済みシンボルのページは、まだ更新されていないようです。
[定義済みの条件シンボル](http://docwiki.embarcadero.com/RADStudio/Sydney/ja/%E6%9D%A1%E4%BB%B6%E4%BB%98%E3%81%8D%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%EF%BC%88Delphi%EF%BC%89#.E5.AE.9A.E7.BE.A9.E6.B8.88.E3.81.BF.E3.81.AE.E6.9D.A1.E4.BB.B6.E3.82.B7.E3.83.B3.E3.83.9C.E3.83.AB)

# まとめ

勢い余って 6 個書きましたが、これからはコードがすっきりと書けそうですね。