C# 8.0 の null 許容参照のシーケンスをフィルターし、非 null のみを保持する便利な方法はありますか? 質問する

C# 8.0 の null 許容参照のシーケンスをフィルターし、非 null のみを保持する便利な方法はありますか? 質問する

次のようなコードがあります:

IEnumerable<string?> items = new [] { "test", null, "this" };
var nonNullItems = items.Where(item => item != null); //inferred as IEnumerable<string?>
var lengths = nonNullItems.Select(item => item.Length); //nullability warning here
Console.WriteLine(lengths.Max());

このコードを次のように便利に記述するにはどうすればよいでしょうか。

  • 型はnonNullItemsとして推論されるため、null 可能性の警告はありませんIEnumerable<string>
  • 次のようなチェックされていない非NULL可能性アサーションを追加する必要はありませんitem!(コンパイラの健全性チェックの恩恵を受けたいので、エラーのないコーダーであることに頼りたくないからです)。
  • 実行時にチェックされる非 null 可能性アサーションは追加しません (コード サイズと実行時の両方で無意味なオーバーヘッドであり、理想よりも遅く失敗する人為的エラーの場合にも無意味であるため)。
  • ソリューションまたはコーディング パターンは、null 許容参照型の他の項目のシーケンスに、より一般的に適用できます。

C# 8.0 コンパイラのフローに敏感な型付けを活用するこのソリューションは知っていますが、あまりきれいではありません。主に、非常に長くてノイズが多いためです。

var notNullItems = items.SelectMany(item => 
    item != null ? new[] { item } : Array.Empty<string>())
);

もっと良い代替案はありますか?

ベストアンサー1

何らかの方法でコンパイラーを支援する必要があると思います。呼び出しは、.Where()null 以外を返すので安全ではありません。Microsoft は、あなたのような基本的なシナリオを判断するためのロジックを追加できるかもしれませんが、私の知る限り、現時点ではそうではありません。

ただし、次のような単純な拡張メソッドを記述することもできます。

public static class Extension
{
    public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> o) where T:class
    {
        return o.Where(x => x != null)!;
    }
}

おすすめ記事