0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

今どきの C# を久しぶりに触ってみた話(.NET 3.5 → net10.0) パターンマッチング編

0
Last updated at Posted at 2026-03-31

はじめに

現在私はXD.GROWTHで主にGo言語を使っています。

長らくC#から離れています。
最後に本格的に触っていたのは C# / .NET Framework 3.5 の頃です。
Go言語を使っていると、C#ならこんな書き方できるのになぁと思うことも多々あります。

このシリーズでは数回に分けてC#を久しぶりに触ってみて

  • 「こんな書き方ができるようになったのか」と驚いた点
  • 久しぶりに触ってみて、正直「やっぱり不便だな」と感じた点

を中心に、コードを交えながら紹介します。

今回のテーマ

今回のテーマは パターンマッチング です。

特にこのあたり:

  • is がただの型チェックではなくなっている
  • && / || の代わりに and / or / not
  • 条件式の中で変数が生える
  • しかもその変数、if の外でも使える

正直、最初はかなり混乱しました。


昔の書き方(.NET 3.5 時代)

まずは懐かしいコードから。

if (obj != null && obj is string)
{
    string s = (string)obj;
    Console.WriteLine(s.Length);
}

または

var s = obj as string;
if (s != null)
{
    Console.WriteLine(s.Length);
}

特徴

  • 型チェックとキャストが分離している
  • null チェックが必須
  • 同じ変数名を2回書くことが多い

今どきの書き方①:is で変数が生える

if (obj is string s)
{
    Console.WriteLine(s.Length);
}

これだけです。

ポイント

  • is型チェック + 代入 を兼ねる
  • s はキャスト済み
  • null も自動的に弾かれる

これは本当に便利。最初に感動したポイントです。


今どきの書き方②:&& / || の代わりに and / or

さらに進むとこうなります。

if (obj is string s && s.Length > 0)

…ではなく、

if (obj is string s and { Length: > 0 })

何が起きているか

  • and はパターン同士の結合
  • { Length: > 0 } はプロパティパターン

つまり:

「string であり、かつ Length > 0」

を宣言的に書いています。


今どきの書き方③:or / not も使える

if (obj is not string)
{
    return;
}

または

if (obj is string or int)
{
    // どちらか
}

特に重要なのが not

if (obj is not string s)
{
    return;
}

このコード、直感的にどう見えるでしょうか?

「string じゃないなら s に入る?」

と思いがちですが、実際は逆です。


重要ポイント:not の後に入る変数は「否定されていない値」

if (obj is not string s)
{
    return;
}

// ここで s は string
Console.WriteLine(s.Length);

何が起きているか

  • obj is not string sfalse のとき
  • つまり obj is string strue
  • そのときだけ if を抜ける

結果:

s は「string のときだけ存在する変数」

になります。

これはかなりトリッキーです。


さらに驚き:if の右端で作った変数が外で使える

これも最初かなり違和感がありました。

if (obj is not string s)
{
    return;
}

// ここで s が使える
Console.WriteLine(s.Length);

なぜこうなるのか

C# のパターン変数は:

「条件が成立する経路でのみ有効」

というスコープを持っています。

つまりこの場合:

  • return によって「失敗パス」が消える
  • 残るのは「成功パス(string)」だけ

結果として:

if の外なのに、変数が安全に使える


昔との対比

if (!(obj is string))
{
    return;
}

var s = (string)obj;

if (obj is not string s)
{
    return;
}

かなりスッキリしました。


ちょっと混乱するポイント

正直、以下は慣れるまで違和感がありました。

① 記号と単語が混在している

&&    and
||    or
!     not
  • 論理演算子は従来通り使える
  • でもパターンでは別の記法

「どっちを使うのが正しいのか?」と迷う


② 読み方が直感とズレることがある

if (obj is not string s)

これは

「string じゃないなら s」

ではなく

「string でないなら脱出。残りは string」

という意味になります。


③ 変数のスコープが“制御フロー依存”

if (obj is string s)
{
    return;
}

// ここでは s は使えない
if (obj is not string s)
{
    return;
}

// ここでは s が使える

この差はかなり重要です。

さいごに

今どきの C# のパターンマッチングは、

  • 型チェック
  • null チェック
  • プロパティ検証
  • 変数定義

をすべて一箇所にまとめられる強力な仕組みです。

ただし、

  • not の挙動
  • スコープの決まり方
  • 記法の多さ

など、最初は戸惑うポイントも多いです。

昔の C# は:

「手続き的に安全に書く言語」

でしたが、

今の C# は:

「条件を宣言的に記述する言語」

にかなり近づいています。

いかがだったでしょうか。
ご意見ご感想などありましたら、いただけると作者は喜びます。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?