18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【.NET 10 Preview3】C# 14 新機能まとめ

Last updated at Posted at 2025-04-11

extensionブロック

静的メソッド、インスタンスプロパティ、静的プロパティの拡張がサポートされ、これまで以上に多彩な拡張が可能になりました。
C# 13まではメソッドのみが拡張可能でした。

public static class Extensions
{
    public static IEnumerable<int> WhereGreaterThan(this IEnumerable<int> source, int threshold) 
        => source.Where(x => x > threshold);
}

この例では、thisキーワードが付けられたsourceパラメーターがレシーバーです。しかしプロパティ宣言には、同じようなレシーバーの指定場所がありません。そこでC# 14では「extensionブロック」が導入されました。これは、レシーバーをそのブロック内のメンバーに公開するスコープです。
先ほどのWhereGreaterThanメソッドを書き換え、さらにIsEmptyプロパティを追加すると以下のようになります。

public static class Extensions
{
    extension(IEnumerable<int> source) 
    {
        public IEnumerable<int> WhereGreaterThan(int threshold)
            => source.Where(x => x > threshold);

        public bool IsEmpty
            => !source.Any();
    }
}

使い方は簡単です。

var list = new List<int> { 1, 2, 3, 4, 5 };
var large = list.WhereGreaterThan(3);
if (large.IsEmpty)
{
    Console.WriteLine("No large numbers");
}
else
{
    Console.WriteLine("Found large numbers");
}

ジェネリックにも対応しており、解決ルールは従来の拡張メソッドと同じです。以下のようにWhereGreaterThanIsEmptyをジェネリックにすることもできます。
ここでINumber<T>の制約は、> 演算子を使用可能にするために必要です。

extension<T>(IEnumerable<T> source)
    where T : INumber<T>
{
    public IEnumerable<T> WhereGreaterThan(T threshold)
        => source.Where(x => x > threshold);

    public bool IsEmpty
        => !source.Any();
}

静的メソッドや静的プロパティにはレシーバーが不要なので、extensionブロックでは型だけを指定します。

extension<T>(List<T>)
{
    public static List<T> Create()
        => [];
}

extensionブロックはこれまでの拡張メソッドと共存可能です。既存の構文に変える必要はなく、両者はまったく同じように実行されます。
既存の拡張メソッドを含む静的クラスにextensionブロックを追加するだけでOKです。

public static class MyExtensions
{
    // 従来の拡張メソッド
    public static IEnumerable<int> WhereEven(this IEnumerable<int> source)
        => source.Where(x => x % 2 == 0);

    // 新構文:extension ブロック
    extension(IEnumerable<int> source)
    {
        public bool IsEmpty => !source.Any();

        public int SumAll() => source.Sum();
    }

    // 静的メンバーの拡張(新構文)
    extension<T>(List<T>)
    {
        public static List<T> CreateEmpty() => new List<T>();
    }
}

今後のリリースではさらに多くの拡張がサポートされる予定とのこと。

Null条件付き代入

null条件演算子「?.」を右辺値(読み取り)だけでなく、左辺値(代入対象)でも使用できるようになります。
以下のようなUpdateAgeメソッドを例にします

public class Customer
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class UpdateCustomer
{
    public static void UpdateAge(Customer? customer, int newAge)
    {
        if (customer is not null)
        {
            customer.Age = newAge;
        }
    }
}

Null条件付き代入を使うことで、UpdateAgeメソッドを以下のように書き換えることが可能になります。customernullでなければAgeを更新し、nullであれば何もしません。

public static void UpdateAge(Customer? customer, int newAge)
{
    customer?.Age = newAge;
}

IDEが、この変更を提案するために電球アイコン:bulb:でサポートしてくれるようになるそうです。

参考

18
6
0

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
18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?