TEncodingを拡張する。
普段から何かとデフォルト文字コードがShiftJISだったりして、DelphiでもShiftJISを扱いたい。だけどDelphiで使おうと思ったら、
var enc: TEncoding; begin enc := TEncoding.GetEncoding(932); try // ShiftJISを扱う処理 finally enc.Free; end; end;
などといちいち生成して解放してやる必要があって(起動時辺りに作っておいて使いまわしてもいいけど)、やたらめんどくさい。
だからこうする。
unit Lyna.Strings; interface uses Windows, SysUtils; type TEncodingHelper = class helper for TEncoding strict private class var FSJISEncoding: TEncoding; class function GetSJIS: TEncoding; static; private class procedure FreeHelperEncodings; public class property SJIS: TEncoding read GetSJIS; end; implementation { TEncodingHelper } class procedure TEncodingHelper.FreeHelperEncodings; begin FreeAndNil(FSJISEncoding); end; class function TEncodingHelper.GetSJIS: TEncoding; var LEncoding: TEncoding; begin if FSJISEncoding = nil then begin LEncoding := TMBCSEncoding.Create(932); if InterlockedCompareExchangePointer(Pointer(FSJISEncoding), LEncoding, nil) <> nil then LEncoding.Free; end; Result := FSJISEncoding; end; initialization finalization TEncoding.FreeHelperEncodings; end.
あとはこのユニットをusesしてやれば、TEncoding.SJISプロパティが使えるようになるという仕組み。クラスヘルパーばんじゃい。これは単なる例なので、EUC-JPやらJISやらEUC-KRやらBig-5なんかを追加してみたりすると実用的。
正直なところを言えば解放処理はclass destructorでやりたかったんだけど、クラスヘルパーで宣言しても呼び出してくれないみたい。使えねえ仕様だ…。このせいで苦肉の策としてfinalization部を使わざるを得ず。あ、もちろん使い方はTEncoding.ASCIIやTEncoding.UTF8といったのと同じでございます。
しかしなー、どうせプログラム内ではひとつのコードページに対してひとつインスタンスがあればいいんだから*1、GetEncoding内でまだ生成されてなければ内部リストに追加して返す、生成されてたらリストから探して返す、そして終了時に全部一括解放、みたいにしてくれれば使いやすかったのに。.NETから色々パクるのは正直便利になっていいんだけど、GCがないって前提で移植してくれないと利便性さがりまくりんぐだよ。