あのぞんブログ

各言語特有っぽい構文: C#

2025-12-09

この記事は

9 日目の記事です。

個人的な好みを交えて紹介します。

二分探索のサンプルコード

言語の特徴をあえて使い実装している。

// C# - パターンマッチング + switch式 + null許容型
using System;
using System.Collections.Generic;

class Program
{
    static int? BinarySearch<T>(IList<T> arr, T target) where T : IComparable<T>
    {
        var (left, right) = (0, arr.Count - 1);

        while (left <= right)
        {
            var mid = (left + right) >> 1;
            (left, right) = arr[mid].CompareTo(target) switch
            {
                0 => (mid, mid),  // 見つかった
                < 0 => (mid + 1, right),
                > 0 => (left, mid - 1)
            };
            if (arr[mid].CompareTo(target) == 0) return mid;
        }
        return null;
    }

    static void Main()
    {
        var arr = new[] { 1, 3, 5, 7, 9 };
        Console.WriteLine(BinarySearch(arr, 5) ?? -1);  // 2
    }
}

ピックアップ構文

switch 式 (C# 8.0+)

値を返す式として使える switch 文。

// 式として値を返す
var result = value switch
{
    1 => "one",
    2 or 3 => "two or three",
    > 10 => "large",
    _ => "other"
};

// タプルパターン
var quadrant = (x, y) switch
{
    (> 0, > 0) => "Q1",
    (< 0, > 0) => "Q2",
    (< 0, < 0) => "Q3",
    (> 0, < 0) => "Q4",
    _ => "origin or axis"
};

パターンマッチング

型やプロパティの値に基づいてパターンマッチングができる。

// 型パターン
if (obj is string s) { Console.WriteLine(s.Length); }

// プロパティパターン
if (person is { Name: "Alice", Age: > 18 }) { }

// リストパターン (C# 11)
if (arr is [var first, .., var last]) { }

LINQ

統合されたクエリ構文でコレクションやデータソースを操作できる。

// クエリ構文
var result = from x in numbers
             where x > 0
             select x * 2;

// メソッド構文
var result = numbers
    .Where(x => x > 0)
    .Select(x => x * 2)
    .ToList();

とてもスマートに書けて良い。ラムダを渡す必要もない。

ラムダ式と式形式メンバー

簡潔にラムダ式やメソッド・プロパティを式形式で定義できる。

// ラムダ
Func<int, int> square = x => x * x;

// 式形式メソッド
public int Double(int x) => x * 2;

// 式形式プロパティ
public string Name => $"{FirstName} {LastName}";

メソッドでも代入文なしに書けるのは特徴的。

拡張メソッド

既存のクラスを変更せずに新しいメソッドを追加できる。

// 既存のクラスにメソッドを追加(クラス変更不要)
public static class StringExtensions
{
    // this キーワードで対象の型を指定
    public static bool IsNullOrEmpty(this string? s) => string.IsNullOrEmpty(s);
    public static string Reverse(this string s) => new(s.Reverse().ToArray());
}

// 使用:インスタンスメソッドのように呼べる
"hello".Reverse();        // "olleh"
string? s = null;
s.IsNullOrEmpty();        // true

// LINQも拡張メソッドで実装されている
numbers.Where(x => x > 0);  // IEnumerable<T> への拡張

null 許容型と null 合体演算子

null を許容する型と null 時のデフォルト値を提供する演算子。

// null許容値型
int? value = null;
int result = value ?? 0;

// null合体代入
value ??= 10;

// null条件演算子
var length = str?.Length ?? 0;
arr?[0]?.ToString();

タプルと分解

複数の値をグループ化して返したり、変数に分解代入できる。

// タプルリテラル
var point = (x: 10, y: 20);
Console.WriteLine(point.x);

// 分解代入
var (left, right) = (0, arr.Length - 1);
(left, right) = (right, left);  // スワップ

© 2026 あのぞんびより