C# 14 introduces required members, a language feature that allows developers to enforce that certain properties or fields must be initialised when creating an object. This addition increases type safety, immutability, and clarity, particularly in domain modeling, DTOs, API models, and enterprise applications.
This guide covers everything about required members: syntax, enforcement, constructors, records, advanced patterns, compiler behavior, and practical applications.
1. What Are Required Members?
A required member is a property or field that must be initialised either via an object initialiser or constructor before the object is considered valid. Attempting to create an object without initialising required members results in a compile-time error.
Key Points:
- Applied using the
requiredmodifier. - Supported for properties, fields, and auto-properties.
- Works with records, classes, structs, and immutable objects.
- Helps enforce object invariants and domain correctness.
2. Basic Syntax
public class Person
{
public required string Name { get; set; }
public required int Age { get; set; }
}
var person = new Person
{
Name = "Alice",
Age = 30 // Must be initialised, otherwise compile-time error
};
requiredensures Name and Age are set.- Compilation fails if either is omitted.
3. Required Members with Constructors
Required members can coexist with constructors, giving flexibility in object initialisation:
public class Product
{
public required string SKU { get; set; }
public required decimal Price { get; set; }
public Product(decimal price)
{
Price = price; // Constructor can initialise required members
}
}
// Usage:
var product = new Product(99.99m) { SKU = "ABC123" };
- Members can be set via constructor or initialiser, giving hybrid initialisation.
- Improves API flexibility while maintaining invariants.
4. Required Members with Records
Required members are particularly useful with records for immutable data models:
public record Order
{
public required int OrderId { get; init; }
public required string Customer { get; init; }
}
// Initialisation
var order = new Order
{
OrderId = 101,
Customer = "Alice"
};
- Works naturally with
initproperties. - Enforces immutability and mandatory initialisation.
5. Interactions with Object Initialisers
Required members are enforced at compile-time when using object initialisers:
public class Address
{
public required string Street { get; set; }
public required string City { get; set; }
}
var addr = new Address
{
Street = "123 Main St"
// Missing City → Compile-time error!
};
- Ensures developer cannot forget critical properties.
- Particularly valuable for DTOs, configuration objects, and API payloads.
6. Advanced Features
6.1 Default Values
You can provide defaults for required members but still require explicit initialisation:
public class Config
{
public required int Timeout { get; set; } = 30; // Default
}
- Compiler still enforces initialisation if default is insufficient.
- Useful for optional override scenarios.
6.2 Required Members and Inheritance
public class Base
{
public required string BaseProp { get; set; }
}
public class Derived : Base
{
public required string DerivedProp { get; set; }
}
// Must initialise both BaseProp and DerivedProp
var obj = new Derived { BaseProp = "A", DerivedProp = "B" };
- Required members propagate across inheritance hierarchies.
- Ensures all critical properties are set, even in derived types.
6.3 Required Members with init-only Properties
- C# 14 allows
required+initfor immutable required members. - Ensures compile-time enforcement and immutability after initialisation.
public record Settings
{
public required string ApiKey { get; init; }
}
- Prevents accidental reassignment post-construction.
7. Real-World Use Cases
| Scenario | Example |
|---|---|
| Domain Models | Required properties ensure object invariants (e.g., Name and Age in Person). |
| DTOs / API Models | Prevents missing required payload fields (e.g., CustomerId in request). |
| Configuration Objects | Forces developers to initialise critical config (e.g., connection strings). |
| Records and Immutables | Enforces mandatory properties at compile-time in immutable objects. |
| Enterprise Systems | Reduces runtime null reference exceptions by enforcing initialisation at compile-time. |
8. Compiler Behavior and Enforcement
- Compile-time enforcement only: runtime checks are not required.
- Error messages are explicit, indicating which required member is missing.
- Works seamlessly with nullable reference types for safer APIs.
- Enables stronger static analysis and code contracts.
9. Performance Considerations
- No runtime cost: enforcement occurs at compile-time.
- Safe-by-design: eliminates the need for manual null checks in many scenarios.
- Optimises maintainability: ensures developers cannot bypass critical initialisation rules.
10. Best Practices
- Use
requiredfor all critical properties that must be initialised. - Combine with
initfor immutability guarantees. - Use in records and DTOs to improve API safety.
- Propagate required members in base classes and inheritance hierarchies.
- Avoid using
requiredon properties that can safely remain optional.
11. Required Members vs Constructors
- Constructors: allow mandatory initialisation but may be verbose for many properties.
- Required members: enforce initialisation without defining multiple constructors, particularly with object initialisers.
- Combination: use constructors for mandatory logic, required members for flexible initialisation.
12. Summary
Required members in C# 14 provide:
- Compile-time enforcement of mandatory properties.
- Integration with records, classes, structs, and object initialisers.
- Compatibility with init-only properties for immutable objects.
- Safer domain modeling, DTOs, and configuration objects.
- Reduced runtime errors and increased code clarity.
Impact: Required members are a compile-time contract, making your objects self-documenting, safe, and easier to maintain. They are particularly valuable in enterprise applications, APIs, immutable models, and complex object hierarchies.