PaPoo
cover
technews
Author
technews
世界の技術ニュースをリアルタイムでキャッチし、日本語でわかりやすく発信。AI・半導体・スタートアップから規制動向まで、グローバルテックシーンの「今」をお届けします。

C#のメモリ安全性が変わる:unsafe を「危険な記法」から「守るべき契約」に進化させる話

キーポイント


この記事は何の話?

Microsoft の .NET Blog で、C# のメモリ安全性を大きく改善する構想が紹介されました。
ざっくり言うと、​**unsafe キーワードの意味を作り直す** という話です。

これまでの unsafe は、ポインタを使うための「危ないモード」のようなものでした。もちろんそれでも十分に意味はあったのですが、今回の変更はもっと踏み込んでいます。
unsafe を「このコードは危ないかもしれない」ではなく、​​「ここには安全性について、呼び出し側と実装側の契約がある」​ という形で扱おうとしているんですね。

この発想、かなり面白いと思いました。
危険なコードを完全に禁止するのではなく、​危険を見える化して、レビューできるようにする。現実的で、しかも今の時代に合っています。


まず前提:C# はもともと安全な言語寄り

C# は普通に書く分にはかなり安全です。

image_0003.svg

たとえば:

つまり、​ふつうの C# は「危ないことが起きにくい」設計 なんです。

でも、unsafe を使うと話が変わります。
ここでの unsafe は、ざっくり言えば コンパイラやランタイムが全部は守ってくれない領域 に入る、ということです。

Microsoft の説明では、unsafe code が必要になる理由は主に2つ。

これは現実的です。
OS や既存ライブラリとの接続、あるいは低レベル最適化では、こういう領域がどうしても必要になります。完全に消すのは無理、だからこそ 扱い方を厳密にする のが今回のテーマです。


今回の変更の中心:unsafe は「構文」ではなく「契約」になる

ここが一番重要です。

image_0004.svg

従来の unsafe は、どちらかというと「ポインタを使えるようにするためのスイッチ」でした。
しかし新しいモデルでは、unsafe安全性に関する責任が呼び出しグラフを通じて伝播する印 になります。

つまり、

が、コード上で見えるようになるわけです。

個人的には、これはかなり筋がいいと思います。
危険なコードの怖さって、「危ない」こと自体より、​どこまでが安全でどこからが自己責任なのか分かりにくい ことにあるので。
そこを言語レベルで線引きしようとしているのは、かなり賢いです。


新しいモデルの考え方:安全性は「層」で伝わる

記事では、unsafe の扱いを次のような層で説明しています。

1. 内側の unsafe { } ブロック

危険な操作は、まず 内側の unsafe { } ブロック に閉じ込める必要があります。

image_0005.svg

ここでの危険な操作には、たとえば:

が含まれます。

要するに、
​「ここから先は危ない処理です」とコード上で囲う 形です。

これ、地味ですがかなり大事です。
危険な処理が散らばるとレビュー不能になるので、まず 危ない部分を局所化する。これはソフトウェア設計の基本としても気持ちいいですね。


2. 伝播(propagation)

もしメソッドの内部で unsafe な処理を使っていて、その責任を呼び出し側にも伝えたいなら、​そのメソッド自体を unsafe として宣言 します。

すると、そのメソッドを呼ぶ側にも「この呼び出しには安全性上の注意が必要です」という情報が伝わります。

つまり、unsafe は単発の印ではなく、​呼び出しチェーンを通じて広がる契約 になるわけです。

これは Rust や Swift に近い方向だと記事は説明しています。
C# もついに、より厳密で伝播型の unsafe に寄っていく、という感じです。

image_0006.svg


3. /// <safety> コメント

unsafe member には、​**/// <safety> ブロック** で契約を書くことが強く推奨されます。

これは「このメソッドを安全に使うには、呼び出し側が何を保証すべきか」を説明する文書です。

たとえば:

といった内容が入るイメージです。

これがあると何が良いか。
レビューできる んです。

暗黙の「たぶん大丈夫」ではなく、明文化された「ここを満たせば安全」という話になる。
私はこれ、かなり実務向きだと思います。AI がコードを書く時代ならなおさら、コメントは飾りではなく 安全性の契約書 になっていくはずです。


4. 境界での抑制(suppression at the boundary)

あるメソッドの中に unsafe ブロックがあっても、そのメソッド自身を unsafe にしない場合があります。
このとき、そのメソッドは unsafe と safe の境界 になります。

image_0008.svg

ここで必要なのは、unsafe 側の責務をちゃんと「引き受けて解消する」ことです。
つまり、呼び出し側に危険を押し付けずに済むよう、次のどれかで保証する必要があります。

たとえば malloc が「返したポインタは少なくとも size bytes 有効」という保証を持つなら、それを前提として安全側に戻す、という考え方です。

この「境界で責任を解消する」という見方は、かなり実務的です。
unsafe を単に増やすのではなく、​どこで安全に戻すか を設計の中心に置いているのがいいですね。


何が変わるのか:C# 1.0 時代の unsafe とは別物になる

C# 1.0 の unsafe は、主に「ポインタ関連の機能を使えるようにする」ためのものでした。

たとえば:

image_0009.svg

今回の変更では、これがもっと厳密になります。

主な変更点

最後の点は地味に大きいです。
今後は、​ポインタ型があるだけではなく、そのポインタをどう扱うか が重要になります。
要するに、「型が怖い」ではなく「操作が怖い」に寄せているんですね。


IntPtr ではなく typed pointers を勧めているのも面白い

記事では、新しいコードでは IntPtr より byte* のような typed pointer を勧めています。
本当に opaque(中身を知らない)なポインタなら void* を使う、という話も出ています。

さらに、既存の IntPtr ベース API には、必要なら:

という方向も示されています。

このあたり、かなり実践的です。
IntPtr は便利ですが、何でも入るぶん意味がぼやけやすい。
typed pointer のほうが「これは何のポインタか」がわかるので、レビューもしやすいはずです。

image_0013.svg


なぜ今これをやるのか? AI の時代だから

この記事で特に印象的だったのが、​AI-assisted code generation への言及です。

コード生成が速くなると、ソフトウェアの生産量は増えます。
でも人間のレビュー速度は、そんなに急には上がりません。

すると何が起きるかというと、

という問題が出てきます。

だからこそ、unsafe を 見える契約 にしておく必要がある、というのが Microsoft の主張です。
これは単なる言語デザインの話ではなく、​AI 時代の開発体制の話 でもあります。

私はここにかなり現代性を感じました。
これからの言語機能は、「人間が上手に書くため」だけじゃなく、​機械が生成したコードを人間が監査しやすくするため にも設計されるんだろうな、と思います。

image_0014.svg


導入はいつ?

記事によると、この新しいモデルと構文は:

の予定です。

また、最初は opt-in、つまり自分で有効化する形式になります。
そして将来的には、Nullable Reference Types のようにテンプレートが新モデルを有効にする方向へ進むかもしれない、という説明でした。

つまり、すぐに世界がひっくり返るわけではないけれど、
ゆっくり、でも確実に新しい標準へ移行していく 流れです。


率直な感想:これは「怖いコードを怖いままにしない」ための進化

この変更、地味に見えてかなり大きいです。

image_0015.svg

unsafe は昔から「必要だけど危ないもの」でした。
でも危ないものを危ないまま放置すると、結局はレビュー不能になります。
今回の設計はそこをちゃんと踏み込んでいて、​危険を構文ではなく責任の流れとして扱う のが本質だと思います。

特にいいのは、unsafe を「特別な呪文」ではなく、
“誰が何を保証するのか” を明文化する仕組み に変えようとしている点です。

もちろん、これで unsafe が魔法のように安全になるわけではありません。
むしろ逆で、​unsafe を書く難しさはそのまま残る はずです。
でも、その難しさを隠さず、レビュー可能な形に整える。そこがすごく誠実だと思いました。


まとめ

C# の新しい memory safety モデルは、unsafe を単なる「危険な構文」から、​安全性の契約を明示する仕組み へと進化させます。
unsafe { } ブロック、契約の伝播、/// <safety> コメント、境界での責務解消といった仕組みで、危険なコードを見える化するのが狙いです。

AI によるコード生成が当たり前になっていく中で、これはかなり重要な方向転換だと思います。
「書けること」より「レビューできること」を重視する。
C# はそこに向かって、かなり本気で舵を切っているように見えます。


参考: Improving C# Memory Safety - .NET Blog

同じ著者の記事