当前位置: 首页 > news >正文

【C#】构造函数实用场景总结

文章目录

  • 前言
  • 一、构造函数是什么?
  • 二、构造函数的用法
    • 1.初始化对象,避免无效状态
    • 2 初始化静态成员
    • 3 构造函数重载
    • 4.构造函数链
    • 5. 单例模式,多次实例化保持一个对象
    • 6. 依赖注入
    • 7. 初始化只读对象


前言

构造函数是我们平常编程里经常能碰到的老伙计了,构造函数本质上是类中一种特殊的成员方法,用于在实例化对象的时候,对该类中的一些状态进行初始化。本篇文章总结下工作中经常能碰到的使用构成函数的场景,希望能帮助到大家。

一、构造函数是什么?

构造函数可以理解成一个特殊的方法,当一个类被实例化时,这个构造函数会被自动调用,用作初始化这个对象。但是,构造函数的功能根据应用场景,可以扩展为不同的用法。

二、构造函数的用法

1.初始化对象,避免无效状态

很多时候初始化对象,需要给对象设定一种状态,我哪一种业务逻辑举例。卖出去的商品价格不能为负数,库存数量也不能小于零。

这里构造函数最的作用是保证商品对象在创建时就处于有效状态,避免因价格设置错误,库存数量设置错误导致后续逻辑出错,作为一个业务逻辑的检验之用。

internal class Product
{public string productId { get; }/// <summary>/// 价格 > 0/// </summary>public double price { get;  }/// <summary>/// 库存 > 0/// </summary>public int stock { get; }// 构造函数:初始化+参数校验public Product(String productId, double price, int stock){this.productId = productId;// 校验价格合法性,非法则抛出异常,阻止对象创建if (price < 0){throw new ArgumentOutOfRangeException("商品价格不能为负数:" + price);}this.price = price;// 校验库存合法性if (stock < 0){throw new ArgumentOutOfRangeException("商品库存不能为负数:" + stock);}this.stock = stock;}
}

2 初始化静态成员

静态变量,静态属性这类成员属于类本身,而非类的实例。它的初始化方式就是通过构造函数初始化的。确保了静态成员在类的整个生命周期中保持一致的初始状态,适合存储全局共享的数据。

比方说一个日志类需要一个属性存放文件目录,用静态属性的方式就很合适,使用构造函数初始化静态成员。

internal class log
{public static string PhyPath { get; private set; }static log(){PhyPath = AppDomain.CurrentDomain.BaseDirectory;}
}

3 构造函数重载

构造函数重载允许一个类定义多个构造函数,这些构造函数具有相同的名称但参数不同,包括不限于参数个数,参数类型,参数顺序。这是一种灵活的初始化方式,从而应对实例化的时候的各种场景。

这里提供两种构造函数,一个参数是包含电影名称和描述信息,另一个构造函数只包含电影名称,这样实例化Movie类的时候,就能通过两种方式实例化Movie。为对象提供多种初始化方式,满足不同场景的需求

internal class Movie
{public int Id { get; set; }public string MovieName { get; set; }public string Desc { get; set; }public Movie(string MovieName){this.MovieName = MovieName;this.Desc = "";}public Movie(string MovieName,string Desc){this.MovieName = MovieName;this.Desc = Desc;}}

4.构造函数链

子类继承父类的时候,子类可以通过base关键字调用父类的构造函数,实现子类向父类传递参数的情况,也能避免重复代码。

比方说我有一个父类,提供一个构造函数,子类可以通过调用父类的构造函数实现状态的配置化。

/// 父类
public BaseClass(String HttpMethod)
{if (HttpMethod.ToUpper() == "GET"){_httpRequest = HttpContext.Current.Request.QueryString;}if (HttpMethod.ToUpper() == "POST"){_httpRequest = HttpContext.Current.Request.Form;}
}/// 子类
public ChiledClass() : base(HttpContext.Current.Request.HttpMethod)
{
}

5. 单例模式,多次实例化保持一个对象

在数据操作这类服务,经常是能碰到使用单例模式的场景。多次实例化一个数据服务对象,返回的任然是同一个实例,禁止外部直接创建对象。这样既能保证资源利用的最大化,并且类能自主控制创建规则,保证代码安全性。

比方说初始化一个RedisServer服务,其构造函数是私有的,无法直接通过初始化的时候执行这个构造函数。通过Lazy这延迟初始化工具,确保RedisServer实例在首次被使用时通过调用内部私有的构造函数创建,实现 “懒加载”。最后通过一个静态实例返回lazy.Value 实现单例模式

/// <summary>
/// Redis单例服务
/// </summary>
public sealed class RedisServer
{//私有静态字段,存储唯一实例private static readonly Lazy<RedisServer> lazy = new Lazy<RedisServer>(() => new RedisServer());/// <summary>/// 静态实例/// </summary>public static RedisServer Instance { get { return lazy.Value; } }/// <summary>/// Redis连接对象/// </summary>private readonly ConnectionMultiplexer _redis;/// <summary>/// Redis数据库对象/// </summary>private readonly IDatabase _db;/// <summary>/// Redis单例服务/// </summary>private RedisServer(){/// 逻辑:/// 1. 创建Redis连接对象/// 2. 创建Redis数据库对象}/// <summary>/// 获取Redis数据库对象/// </summary>public IDatabase GetDatabase(){return _db;}
}

6. 依赖注入

依赖注入中,也可以是通过构造函数来实现接收依赖项的。另外就是这里通过构造函数初始化只读属性,这样可以创建不可变对象,实现线程安全。

[Route("api/[controller]/[action]")]
[ApiController]
public class AuthController : ControllerBase
{private readonly ILogger<AuthController> _logger;private readonly IJWTService _jwtService;public AuthController(ILogger<AuthController> logger = null, IJWTService jwtService = null){_logger = logger;_jwtService = jwtService;}[HttpGet]public ActionResult<string> test(){return "test";}[HttpPost]public ActionResult<string> Login([FromBody]LoginUser loginUser) { var token =  _jwtService.GenerateToken(new CurrentUser() { UserId = loginUser.UserId,Name = "张三",Age = 18,NickName = "张三", RoleList = new List<string>() { "admin" } });return token;} 
}

7. 初始化只读对象

只能在构造函数中初始化readonly字段,创建不可变对象,实现线程安全。

代码如上。

http://www.dtcms.com/a/348119.html

相关文章:

  • PostgreSQL interval 转换为 int4 (整数)
  • Flink SQL执行SQL错误排查
  • 结构化智能编程:用树形向量存储重构AI代码理解范式
  • RAGFlow (二)小试牛刀:登陆页重构
  • 《链路状态路由协议OSPF》
  • 前端工程师面试题-vue
  • 记一次生产环境Hbase填坑之路、Hbase客户端登陆、kerberos认证、端口列表、Pod上手撕代码【Hbase最佳实践】
  • 【CV】OpenCV①——OpenCV常用模块
  • 使用 Fargate 在 AWS ECS 上运行 Spring Boot 应用程序
  • 【C#】【WinForm】ListView_列表视图控件
  • [每周一更]-(第157期):深入理解Go语言的垃圾回收机制:调优与监控
  • BERT(Bidirectional Encoder Representations from Transformers)模型详解
  • 2.7 提示词调优编码实战(二)
  • 2025年8月第3周AI资讯
  • 将C++资源管理测试框架整合到GitLab CI/CD的完整实践指南
  • Ansible自动化配置
  • 手写MyBatis第31弹-用工厂模式重构MyBatis的SqlSession创建过程
  • 小迪安全v2023学习笔记(七十一讲)—— Python安全反序列化反编译格式化字符串安全
  • 深入解析MyBatis中#{}和${}的区别与应用场景
  • Implementing Redis in C++ : E(AVL树详解)
  • spring源码之事务篇(事务管理器整个流程)
  • 笔记 | Anaconda卸载重装
  • Hyperledger Fabric官方中文教程-改进笔记(十五)-从通道中删除组织
  • 【机器学习】3 Generative models for discrete data
  • HTML网页游戏五子棋
  • 电路学习(四)二极管
  • Spring框架相关面试题
  • 【机器学习】4 Gaussian models
  • 【网络运维】Shell 脚本编程:while 循环与 until 循环
  • Python自学笔记11 Numpy的索引和切片