"Null values preserved in configuration": source generator and in-memory provider statements don't match .NET 9.0.22 / 10.0.14 behavior

Đang mở Phù hợp với người mới
#56,789 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
1/5
Thời gian dự kiến
Dưới một giờ
Mức phù hợp với người mới
86/100
Loại issue
Tài liệu
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
csharp
Lĩnh vực
documentation

Hướng nghiên cứu

Đọc trang tương thích được liên kết, đặc biệt là mục “Non-nullable value types”, rồi so sánh nhận định đó với bản tái hiện và mã được tạo trong issue. Sửa nhận định để mô tả thời điểm reflection binder và source generator giữ nguyên giá trị ban đầu khi giá trị cấu hình là null hoặc rỗng. Hoàn tất khi trang giải thích chính xác hành vi được báo cáo trong .NET 9 và .NET 10.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Page: https://learn.microsoft.com/dotnet/core/compatibility/extensions/10.0/configuration-null-values-preserved (read 2026-11-08)

Statement on the page (section "Non-nullable value types"):

Providers that store a real null value, such as the in-memory provider, already bound null to non-nullable value-type properties by setting the default value, even before .NET 10, and the configuration source generator also matches this behavior.

What we observe: neither part holds when the property has an initial value.

Repro (Microsoft.NET.Sdk.Web, TargetFrameworks net9.0;net10.0, built once with EnableConfigurationBindingGenerator false and once with true):

using Microsoft.Extensions.Configuration;

var config = new ConfigurationBuilder()
    .AddInMemoryCollection(new Dictionary<string, string?>
    {
        ["Settings:Name"] = "x",
        ["Settings:TimeoutSeconds"] = null,
    })
    .Build();

Settings settings = config.GetSection("Settings").Get<Settings>()!;
Console.WriteLine($"{Environment.Version} TimeoutSeconds = {settings.TimeoutSeconds}");

public sealed class Settings
{
    public string? Name { get; set; }
    public int TimeoutSeconds { get; set; } = 30;
}

Output (SDK 10.0.403, Windows):

Binder .NET 9.0.22 .NET 10.0.14
Reflection 30 0
Source generator 30 30
  • With the in-memory provider, the reflection binder on .NET 9 kept the initial value (30); it did not set default(int).
  • The source generator keeps the initial value on both versions. The generated code assigns a non-nullable value-type property only when the value is neither null nor empty, for example (.NET 10.0.14 generator output):
if (TryGetConfigurationValue(configuration, key: "TimeoutSeconds", out string? value6))
{
    if (!string.IsNullOrEmpty(value6))
    {
        instance.TimeoutSeconds = ParseInt(value6, configuration.GetSection("TimeoutSeconds").Path);
    }
}

The same holds for a JSON null (AddJsonFile): reflection binder 0 on .NET 10, source generator 30 on .NET 9 and .NET 10. So on .NET 10 the same configuration produces different values depending on whether the generator is enabled, which matters for apps where it is on by default (AOT web apps, PublishTrimmed).

Suggested fix: remove or correct the sentence, and mention that the source generator does not bind null (or "") to non-nullable value-type properties, so the initial value is kept.

Ngôn ngữ chính
Không có dữ liệu ngôn ngữ
Star
4.8k
Fork
6.1k
Merge trung bình
1 ngày 1 giờ
Pull request đã merge (30 ngày)
305

Chuẩn bị môi trường

Mở trong Codespaces

Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của dotnet/docs

Tất cả issue của dotnet/docs

Issue tương tự

Thêm issue về Documentation

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.