惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
I
InfoQ
N
Netflix TechBlog - Medium
D
DataBreaches.Net
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
SegmentFault 最新的问题
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
C
Cisco Blogs
T
Threat Research - Cisco Blogs
V
Visual Studio Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园_首页
Recorded Future
Recorded Future
J
Java Code Geeks
The Cloudflare Blog
S
Securelist
人人都是产品经理
人人都是产品经理
T
Tor Project blog
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
V
Vulnerabilities – Threatpost
V
V2EX
P
Palo Alto Networks Blog
I
Intezer
罗磊的独立博客
博客园 - 叶小钗
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Hacker News
The Hacker News
T
The Blog of Author Tim Ferriss
Blog — PlanetScale
Blog — PlanetScale
P
Privacy International News Feed
P
Proofpoint News Feed
美团技术团队
Cisco Talos Blog
Cisco Talos Blog
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
L
LINUX DO - 热门话题
Simon Willison's Weblog
Simon Willison's Weblog
MyScale Blog
MyScale Blog
H
Help Net Security
W
WeLiveSecurity
Google Online Security Blog
Google Online Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

Duende Software Official Site

Duende Software Duende Software Duende Software Duende Software Duende Software Duende Software Duende Software Stop AI Bots from Wasting Your Server How Duende IdentityServer Filters Claims (And Why It Matters) Core vs Extended Protocols in Duende IdentityServer v8: What You Get and When You Need More Your IdentityServer v8 Upgrade Checklist: A Quick Pre-Flight Guide Setting Up SAML Single Sign-On in ASP.NET with Duende IdentityServer Your Identity, Your Terms: Duende's Modular Identity Infrastructure and v8.x Release Duende Spring Launch '26: Identity Infrastructure That Expands With You SAML and OpenID Connect (OIDC): Coexistence, Not Competition The 9 Components of SAML You Need to Know, Ranked by Importance The Cost of NOT Implementing Financial-Grade Security Token Issuer Isolation: Why It Matters for Security and Compliance The Composable Identity Pattern: Build What You Need, Skip What You Don't Multi-Brand Identity: When Your Company Needs More Than One Face Post-Quantum Cryptography in .NET 10: A Practical Guide The Real Cost of Build vs. Buy for Identity OAuth 2.1 Made Simple: The Only Flows You Need Beyond localhost: Multi-Instance ASP.NET Core Deployment with .NET 10 Harden Your .NET JSON Deserialization with System.Text.Json and JsonSerializerOptions.Strict ASP.NET Core Cookie Size Limits in Production: Causes and Fixes The Emergency Stop Button - Implementing Immediate Token Revocation in .NET 10 The 2025 OWASP Top 10 and IdentityServer Update Guidance for CVE-2026-40372 - ASP.NET Data Protection Why a Standard JWT Access Token Matters The Identity Governance Checklist You Wish You Had Six Months Ago The History and Future of SAML: Why a 20-Year-Old Protocol Still Matters The Cookie Apocalypse Already Happened Verify - Open Source Sponsorship Why Identity Is Infrastructure, Not a Feature Extending Duende IdentityServer Server-Side Sessions with Dynamic User Metadata Give Your AI Coding Assistant Duende Expertise with Agent Skills and MCP Server Triggering User Registration via OpenID Connect with Duende IdentityServer Improving .NET Security Code with C# 14 Property Extensions Developing Audit Logs with Duende IdentityServer Events Patch Releases: Addressing CVE-2026-26127 in Microsoft.BCL.Memory Client-Initiated Backchannel Authentication (CIBA) in ASP.NET Core 10 with Duende Identity Server Rate Limiting IdentityServer Endpoints It's Probably DNS - Can You Dig It? Security Lingo Explained: Encode vs Encrypt vs Hash Implementing Zero Trust with Resource Isolation Security Lingo Explained: JWT DPoP Security for .NET APIs with JwtBearer Extensions v1.0.0 Announcing the Duende IdentityServer4 Migration Analysis Tool BenchmarkDotNet - Open Source Sponsorship Security Lingo Explained: PAR Why Signing Key Rotation Matters in OpenID Connect and Duende IdentityServer Security Lingo Explained: OP Duende Year-End Review 2025 Security Lingo Explained: BCP Security Lingo Explained: DPoP Security Lingo Explained: Auth Secure frontend apps with the BFF Pattern Scaling with Duende IdentityServer, MCP, and AI Duende IdentityServer v7.4 is now available Duende BFFv4 is now available Securing OpenAPI and Swagger UI with OAuth in .NET 10 Building a Federation Gateway with Duende IdentityServer: Strategies and Considerations for Identity Orchestration
The field Keyword in C# 14: Write Less, Validate More
Khalid Abuhakmeh · 2026-05-12 · via Duende Software Official Site

You need a property that validates its input. In C# 13 and earlier, that means writing a private backing field, a get accessor that returns it, and a set accessor that validates the value before storing it. Three moving parts for one property:

Csharp

public class Greeting
{
    private string _msg = "Hello";

    public string Message
    {
        get => _msg;
        set => _msg = value ?? throw new ArgumentNullException(nameof(value));
    }
}

One property, one validation rule, three lines of ceremony. The backing field _msg exists only to give set something to write to and get something to read from. It carries no meaning of its own.

Multiply this across a configuration class with five or six validated properties, and the noise adds up fast.

Enter the field Keyword

C# 14 introduces field, a contextual keyword you can use inside property accessors to reference the compiler-generated backing field. You write the accessor that needs custom logic. The compiler generates the other one for you, exactly like an auto-property:

Csharp

public class Greeting
{
    public string Message
    {
        get;
        set => field = value ?? throw new ArgumentNullException(nameof(value));
    }
}

Same validation. No explicit backing field. The get accessor is auto-implemented by the compiler because it has no body, and field in the set accessor points to the compiler-synthesized backing field behind the scenes.

The Rules

  • field is a contextual keyword. It only has special meaning inside a property accessor body. Outside of accessors, field is still a regular identifier.
  • You can use field in get, set, or init accessors. Provide a body for one, both, or just the one that needs logic.
  • You can combine field with a property initializer: public string Name { get; set => field = value.Trim(); } = "Default";

Practical Examples

Input Validation on Configuration Options

Configuration classes are full of properties that need guard clauses. The field keyword cuts the noise:

Csharp

public class OAuthClientOptions
{
    public string ClientId
    {
        get;
        set => field = !string.IsNullOrWhiteSpace(value)
            ? value
            : throw new ArgumentException("ClientId cannot be empty.", nameof(value));
    }

    public Uri RedirectUri
    {
        get;
        set => field = value.IsAbsoluteUri
            ? value
            : throw new ArgumentException("RedirectUri must be an absolute URI.", nameof(value));
    }
}

Each property enforces its contract in the setter. No backing fields cluttering the class. The get accessors are auto-generated.

Lazy Initialization

The field ??= pattern gives you lazy initialization without Lazy<T> or an explicit backing field:

Csharp

public class ExpensiveService
{
    public Connection DatabaseConnection
    {
        get => field ??= CreateConnection();
    }

    private Connection CreateConnection()
    {
        // Imagine this is expensive
        return new Connection("Server=localhost;Database=app");
    }
}

public class Connection(string connectionString)
{
    public string ConnectionString => connectionString;
}

The first time you read DatabaseConnection, it calls CreateConnection() and stores the result. Every subsequent read returns the cached instance. This works because field starts as null (the default for reference types), and ??= only assigns when the left side is null.

One caveat: this is not thread-safe. If multiple threads hit the getter simultaneously, CreateConnection() could run more than once. For thread-safe lazy initialization, stick with Lazy<T>.

Trimming Input on Set

A simple pattern for cleaning up string input:

Csharp

public class Person
{
    public string? FirstName
    {
        get;
        set => field = value?.Trim();
    }
}

Every assignment to FirstName gets trimmed. The caller never needs to remember to trim, and the getter returns the cleaned value without any transformation.

Change Notification (INotifyPropertyChanged)

ViewModels in MVVM apps share the same boilerplate: check whether the value has changed, update the field, and raise the event. The field keyword helps:

Csharp

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class SettingsViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    public string Theme
    {
        get;
        set
        {
            if (field != value)
            {
                field = value;
                OnPropertyChanged();
            }
        }
    } = "Light";

    public int FontSize
    {
        get;
        set
        {
            if (field != value)
            {
                field = value;
                OnPropertyChanged();
            }
        }
    } = 14;

    protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Compare this with the version that declares _theme and _fontSize fields manually. The field keyword removes two fields and two get accessor bodies. The logic stays, the scaffolding goes.

Disambiguating field

Because field is a contextual keyword, it only has special meaning inside a property accessor. But if your class already has a member or local variable named field, you need to disambiguate:

Csharp

public class Sensor
{
    private string field; // a member named "field" — not ideal, but it happens

    public string Reading
    {
        get;
        set
        {
            // "field" here refers to the compiler-generated backing field
            field = value;

            // Use this.field to access the instance member named "field"
            this.field = value;
        }
    }

    public string Label
    {
        get;
        set
        {
            // Use @field to refer to a local variable named "field"
            var @field = value.ToUpper();
            field = @field; // assigns the keyword backing field from the local
        }
    }
}

The disambiguation rules:

Syntax Refers to
field (inside accessor) Compiler-synthesized backing field
this.field Instance member named field
@field Local variable or parameter named field

The simplest fix: rename the member. If you have a member called field, this is a good time to give it a more descriptive name.

Limitations and Gotchas

A few things to know before you use field everywhere:

  • Accessor bodies only. You can't use field in regular method bodies, constructors, or anywhere outside a property accessor. It's scoped to get, set, and init.
  • Compiler-generated name. The backing field gets a compiler-generated name (similar to auto-properties today). You can't reference it by name in reflection or serialization attributes. If you need control over the field name, use an explicit backing field.
  • Field-targeted attributes work, property-targeted ones don't transfer. You can use the [field: NonSerialized] attribute target on a field-keyword property, just like with auto-properties. But property-level attributes like [JsonIgnore] affect the property, not the backing field. If you need an attribute that targets the backing field and no field: target exists for it, you need an explicit backing field.
  • One field per property. Each property gets its own synthesized backing field. You can't share a field between multiple properties.

Clean Configuration Classes for Identity

The options pattern is everywhere in ASP.NET Core. Classes that configure middleware, authentication handlers, and token validation all benefit from validated properties. Here's what a token validation options class looks like with field:

Csharp

public class TokenValidationOptions
{
    public required string Issuer
    {
        get;
        set => field = !string.IsNullOrWhiteSpace(value)
            ? value
            : throw new ArgumentException("Issuer cannot be empty.", nameof(value));
    }

    public required string Audience
    {
        get;
        set => field = !string.IsNullOrWhiteSpace(value)
            ? value
            : throw new ArgumentException("Audience cannot be empty.", nameof(value));
    }

    public TimeSpan ClockSkew
    {
        get;
        set => field = value >= TimeSpan.Zero
            ? value
            : throw new ArgumentOutOfRangeException(nameof(value), "ClockSkew must not be negative.");
    } = TimeSpan.FromMinutes(5);

    public int MaxTokenLifetimeMinutes
    {
        get;
        set => field = value > 0
            ? value
            : throw new ArgumentOutOfRangeException(nameof(value), "MaxTokenLifetimeMinutes must be positive.");
    } = 60;
}

Four validated properties. Zero backing fields. Issuer and Audience are required, so the compiler enforces that callers set them at construction. ClockSkew and MaxTokenLifetimeMinutes have sensible defaults via initializers. Every property enforces its contract at the point of assignment, and any invalid value throws immediately rather than being silently accepted and failing later at runtime.

Configuration classes with validation are everywhere in identity code. Duende IdentityServer uses the options pattern for configuring token lifetimes, issuer URIs, signing credentials, and more. The field keyword makes these classes cleaner without sacrificing the validation that keeps configuration errors from reaching production.

Conclusion

The field keyword solves a narrow problem well: adding logic to a property without the ceremony of an explicit backing field. It won't change how you architect applications, but it will make the properties you write every day a little cleaner. Start using it anywhere you have a backing field that exists only to support a get/set pair.