C# 8.0での追加目標で、using
ステートメント絡みの機能が2つほど。
1つは、パターン ベース(IDiposable
インターフェイスの実装不要)でusing
が使えるようになるというもの。
もう1つは、変数宣言・変数のスコープに紐づいたusing
。
パターン ベースで using
C# の言語機能のいくつかは、単にメソッド呼び出しに変換するだけのシンタックスシュガーが多いです。
foreach
、await
、クエリ式など、いろんなものが「この名前のメソッドさえ実装していればどんな型でも使える」という類の構文になっています。
ですが、微妙にものによって挙動が違ったり。
-
拡張メソッドでもいい
- クエリ式
await
- 分解
- コレクション初期化子 (ただし、C# 6.0 以降)
- インスタンス メソッドでないとダメ
- インターフェイスの実装が必須
ということで、インターフェイスの実装が必須で使い勝手が悪かったusing
ステートメントですが、C# 8.0で、これを「Dispose()
と言うメソッドさえ持っていれば何でも使える」というものに変えるようです。
というのも、ref構造体がインターフェイスを実装できないものの、ref構造体でusing
を使いたい場面が非常に多い状況になっているので。
パターン ベースなusing
の需要がかなり上がっているみたいです。
ちなみに、これはusing
に限った話ではなく、上記のような挙動の差をなくしたいという話でもあります。
C# 8.0では他にも「非同期 foreach
」みたいな話もあって、これと関連して、上記の「foreach
が拡張メソッドのGetEnumerator
を受け付けないのは変じゃない?」みたいなことも言われています。こちらもセット。
using 変数宣言
これまで、using
を使うときには以下のような書き方でした。
using (var d = someDisposable)
{
// このスコープ内を抜けたら Dispose
}
で、C# 8.0 では、以下のような書き方を認めようという話です。
{
// 変数宣言と同時に、その変数を using
using var d = someDisposable;
// 変数のスコープを抜けたら Dispose
}
C# の言語機能としては「using
修飾付きの変数宣言」みたいになるようです。
この機能を追加する主な動機は、以下のような「using
の入れ子」の解消です。
// 同寿命のリソースを何個も使うとき、こんな感じになる
using (var a = someDisposable)
using (var b = anotherDisposable)
using (var c = oneMoreDisposable)
{
// ここを抜けたら Dispose
}
// それをこう変えたい
using var a = someDisposable;
using var b = anotherDisposable;
using var c = oneMoreDisposable;
// メソッドを抜けたら Dispose
これも、fixed
ステートメントにも同じことが言えそう(同寿命で重ねることが結構ある)ということで、
同じような「fixed
変数宣言」も考えているそうです(こちらはたぶんC# 8.0よりも将来の話)。