C#的primary constructor(主构造函数)是从C# 12开始引入的语法特性,允许开发者在类、结构或者记录的声明处直接定义构造函数参数,无需再单独编写构造函数体完成参数赋值,能够有效减少重复代码,在依赖注入场景中也能大幅简化构造器的编写逻辑。

主构造函数的基本语法
传统方式编写类的构造函数时,需要先声明私有字段,再在构造函数中完成赋值,代码示例如下:
// 传统构造函数写法
public class UserService
{
private readonly IUserRepository _userRepository;
private readonly ILogger _logger;
public UserService(IUserRepository userRepository, ILogger logger)
{
_userRepository = userRepository;
_logger = logger;
}
public void AddUser(string userName)
{
_logger.Log($"开始添加用户:{userName}");
_userRepository.Add(userName);
}
}
使用主构造函数后,上述代码可以简化为如下形式:
// 主构造函数写法
public class UserService(IUserRepository userRepository, ILogger logger)
{
private readonly IUserRepository _userRepository = userRepository;
private readonly ILogger _logger = logger;
public void AddUser(string userName)
{
_logger.Log($"开始添加用户:{userName}");
_userRepository.Add(userName);
}
}
主构造函数的参数直接定义在类名后的括号内,类内部可以直接使用这些参数,也可以像上面示例一样赋值给字段。如果不需要额外存储参数,甚至可以直接在方法中使用参数:
public class UserService(IUserRepository userRepository, ILogger logger)
{
public void AddUser(string userName)
{
// 直接使用主构造函数参数
logger.Log($"开始添加用户:{userName}");
userRepository.Add(userName);
}
}
主构造函数在依赖注入中的简化应用
在依赖注入场景中,类的构造函数通常仅用于接收注入的服务并赋值给字段,传统写法会产生大量重复的字段声明和赋值代码。使用主构造函数可以大幅简化这部分逻辑,尤其是当注入的服务数量较多时,简化效果更明显。
以下是依赖注入场景下的传统写法示例:
// 传统依赖注入构造器写法
public class OrderService
{
private readonly IOrderRepository _orderRepository;
private readonly IUserRepository _userRepository;
private readonly ILogger _logger;
private readonly ICacheService _cacheService;
public OrderService(
IOrderRepository orderRepository,
IUserRepository userRepository,
ILogger logger,
ICacheService cacheService)
{
_orderRepository = orderRepository;
_userRepository = userRepository;
_logger = logger;
_cacheService = cacheService;
}
public async Task CreateOrder(string userId, List<string> itemIds)
{
_logger.Log($"用户{userId}创建订单");
var user = await _userRepository.GetByIdAsync(userId);
var order = new Order
{
UserId = userId,
Items = itemIds
};
await _orderRepository.AddAsync(order);
await _cacheService.SetAsync($"order_{order.Id}", order);
}
}
使用主构造函数简化后的代码:
// 主构造函数简化依赖注入构造器
public class OrderService(
IOrderRepository orderRepository,
IUserRepository userRepository,
ILogger logger,
ICacheService cacheService)
{
private readonly IOrderRepository _orderRepository = orderRepository;
private readonly IUserRepository _userRepository = userRepository;
private readonly ILogger _logger = logger;
private readonly ICacheService _cacheService = cacheService;
public async Task CreateOrder(string userId, List<string> itemIds)
{
_logger.Log($"用户{userId}创建订单");
var user = await _userRepository.GetByIdAsync(userId);
var order = new Order
{
UserId = userId,
Items = itemIds
};
await _orderRepository.AddAsync(order);
await _cacheService.SetAsync($"order_{order.Id}", order);
}
}
如果不需要将注入的服务存储为字段,也可以直接在方法中使用主构造函数参数,进一步简化代码:
public class OrderService(
IOrderRepository orderRepository,
IUserRepository userRepository,
ILogger logger,
ICacheService cacheService)
{
public async Task CreateOrder(string userId, List<string> itemIds)
{
// 直接使用主构造函数参数
logger.Log($"用户{userId}创建订单");
var user = await userRepository.GetByIdAsync(userId);
var order = new Order
{
UserId = userId,
Items = itemIds
};
await orderRepository.AddAsync(order);
await cacheService.SetAsync($"order_{order.Id}", order);
}
}
主构造函数的注意事项
- 主构造函数参数在类初始化阶段可用,不能在静态成员中直接使用,因为静态成员属于类级别,不依赖实例初始化。
- 如果类同时定义了主构造函数和传统构造函数,传统构造函数需要调用主构造函数的参数,示例如下:
public class TestClass(int baseValue)
{
private readonly int _baseValue = baseValue;
// 传统构造函数调用主构造函数
public TestClass(int baseValue, int extraValue) : this(baseValue)
{
_extraValue = extraValue;
}
private readonly int _extraValue;
}
- 主构造函数也可以和属性结合使用,直接将参数赋值给属性:
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}
主构造函数作为C#的新语法特性,能够有效减少重复代码,提升开发效率,尤其是在依赖注入场景下的构造器编写中,能够大幅简化代码结构,让代码更简洁易读。开发者在使用时需要注意其适用范围和语法规则,合理运用这一特性优化现有代码。
C#primary_constructor主构造函数依赖注入构造器简化修改时间:2026-06-18 00:21:42