C# 配信でちょくちょく出てくる話題の1つに

「Visual Studio (for Windows)はいまだに .NET Framework だから」

というものがあります。 もちろん、「.NET Core 化はよ」みたいな文脈です。

Visual Studio は .NET 製アプリの中でも大規模なものの1つなわけで、ドッグフーディング的な意味で早く .NET Core 化してほしいというのもありますし。

.NET Framework → .NET 5 → .NET 6 → .NET 7 と、毎度2・3割は速くなってるというベンチマークがあるわけで合計すると2倍以上速いかもしれず、 普通にパフォーマンス上の理由でも早く .NET Core 系になってほしかったりもします。

そしてもう1個、 実は .NET Framework の方は Unicode 8.0 で止まっているという話があったり。

C# の lexer/parser は .NET ランタイム依存

C# では、空白文字とか識別子に使える文字とかの定義に Unicode の文字カテゴリーを使っています。

そして、C# コンパイラー自身が C# 製になって以来、 カテゴリー判定には普通に .NET の GetUnicodeCategory を使っています。

そして、 「Visual Studio は .NET Framework 動作」 と「.NET Framework は Unicode 8.0 止まり」 のコンボで、 Visual Studio 上でだけコンパイルできないコードが割かし簡単に書けたりします。

C# 9.0 以降に追加された letter

C# で識別子に使える文字は、まあかなり端折って言うと、いわゆる letter と言われる文字です。

で、Unicode の各バージョンで追加された文字は、 unicode.org 内の各種データ置き場DerivedAge.txt とかで調べられます。

ちょっと Unicode 8.0 から 14.0 まで1文字ずつそれっぽい letter を適当に拾って…

  • Unicode 8.0: ᏸ U+13F8, Cherokee Small Letter Ye
  • Unicode 9.0: Ɪ U+A7AE, Small Captital I
  • Unicode 10.0: ৼ U+09FC, Bengali Letter Vedic Anusvara
  • Unicode 11.0: ՠ U+0560, Armenian Small Letter Turned Ayb
  • Unicode 12.0: Ꞻ U+A7BA, Latin Capital Letter Glottal A
  • Unicode 13.0: ഄ U+0D04, Malayalam Letter Vedic Anusvara
  • Unicode 14.0: ౝ U+0C5D, Telugu Letter Nakaara Pollu

これを、こうじゃ:

// Unicode 8.0
int  = 8; // U+13F8, Cherokee Small Letter Ye

// Unicode 9.0
int  = 9; // U+A7AE, Small Captital I

// Unicode 10.0
int  = 10; // U+09FC, Bengali Letter Vedic Anusvara

// Unicode 11.0
int ՠ = 11; // U+0560, Armenian Small Letter Turned Ayb

// Unicode 12.0
int  = 12; // U+A7BA, Latin Capital Letter Glottal A

// Unicode 13.0
int  = 13; // U+0D04, Malayalam Letter Vedic Anusvara

// Unicode 14.0
int  = 14; // U+0C5D, Telugu Letter Nakaara Pollu

Console.WriteLine( +  +  + ՠ +  +  + );

(ちなみに C# コンパイラーっていまだにサロゲートペアに対応していないので、BMP 内で当該文字を探さないといけないんですが。 見ての通り、最近でも BMP への文字追加が意外とたくさんあります。)

これをエディターで開いてみましょう。

Visual Studio for Windows (左)と VS Code (右)

左が Visual Studio for Windows、右が VS Code。 .NET Framework が Unicode 8.0 で止まっている証拠の1つとなります。

ちなみに、 .NET SDK のバージョンによってもどこまでコンパイルできるか変わるはずです。 確か、 .NET 6 は Unicode 13.0 なので、 ౝ (U+0C5D、Unicode 14 での追加)はコンパイルできないと思います。

おまけ: 対 Visual Studio 専用ホモグラフ攻撃

ほんとたまたまで、 「DerivedAge.txt を眺めてて各バージョン最初に目に入った letter っぽい文字」 を選んだだけなんですが…

Ɪ と ՠ の2文字、ASCII 文字と似ててホモグラフ攻撃できそうじゃない…

class Ɪՠage { }

この Ɪՠage クラス、最初の2文字が先ほどの Ɪ (U+A7AE)と ՠ (U+0560)です。

これ、たぶん、CI とかも通っちゃうんですよね。 これがコンパイルできないのは本当に Visual Studio for Windows だけ…