次の方法で共有


ConfigurationBinder が無効な配列要素を自動的にスキップする

.NET 8 以降では、 ConfigurationBinder は、値をターゲット型に変換できない配列要素とリスト要素を自動的にスキップします。 以前は、失敗した要素は null プレースホルダーとして保持され、結果のコレクションは構成ソース内の要素の数と同じ長さを保持していました。

導入されたバージョン

.NET 8

以前の動作

以前は、 Get<T>(IConfiguration) または Bind(IConfiguration, Object)を使用して配列またはリスト プロパティをバインドするときに、要素の値をターゲット型に変換できなかった場合、その要素は結果の null プレースホルダーとして保持されていました。 コレクションの長さが、構成内の要素の数と一致しました。

// Configuration source, for example, appsettings.json:
// "Items": [
//   { "Name": "A", "Interval": 10 },
//   { "Name": "B", "Interval": "a" }   <-- invalid int
// ]

var settings = configuration.GetSection("Items").Get<MyItem[]>();

// .NET 6/7 result:
// settings.Length == 2
// settings[0] = { Name = "A", Interval = 10 }
// settings[1] = null   (conversion failed, placeholder preserved)

新しい動作

.NET 8 以降では、型変換に失敗した要素は暗黙的にスキップされます。 結果のコレクションには、正常にバインドされた要素のみが含まれており、構成ソース内のエントリの数よりも短い長さがあります。

var settings = configuration.GetSection("Items").Get<MyItem[]>();

// .NET 8+ result:
// settings.Length == 1
// settings[0] = { Name = "A", Interval = 10 }

破壊的変更の種類

この変更は 動作の変更です。

変更理由

ConfigurationBinderの内部実装は、.NET 8 でリファクタリングされました。 ターゲット配列と要素をインプレースで事前に割り当てる代わりに(変換に失敗した場合はnullが残る)、バインダーは、最終的な配列を作成する前に、正常にバインドされた要素のみを一時リストに集めるようになりました。

以前の動作は、 int[]などの値型でも問題でした。 無効な構成値の場合、バインダーは正当な値である 0 と区別できない0を格納します。 新しい動作では、このあいまいさが回避されます。

  • 開発中に ErrorOnUnknownConfiguration を有効に して、要素をサイレント ドロップするのではなく、無効な構成値をすぐに表示できるようにします。

    var settings = configuration.GetSection("Items").Get<MyItem[]>(options =>
        options.ErrorOnUnknownConfiguration = true);
    

    .NET 8 以降では、このオプションにより、値をターゲット型に変換できない場合にConfigurationBinderをスローし、InvalidOperationExceptionを発生させます。 詳細については、「 ConfigurationBinder throws for mismatched value」を参照してください。

  • 無効な構成値を修正します。 構成ソース内のすべての値が、バインドされたモデルで想定される型と一致していることを確認します。

  • コードが構成ソースと一致する要素の数に依存する場合は、バインド後にコレクションの長さを検証します。

  • 変換できない値を適切に処理し、すべての配列エントリを保持する必要がある場合は、手動解析で文字列プロパティを使用します。

影響を受ける API