【C#】当重复使用一段代码倒计时时,定义接口类和通过实现类继承接口方式进行封装方法和体现代码灵活性

本文主要是介绍【C#】当重复使用一段代码倒计时时,定义接口类和通过实现类继承接口方式进行封装方法和体现代码灵活性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

欢迎来到《小5讲堂》
大家好,我是全栈小5。
这是《C#》序列文章,每篇文章将以博主理解的角度展开讲解,
特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。
温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!

在这里插入图片描述

目录

  • 前言
  • 优化前
    • 界面
    • 代码
  • 优化后
    • 界面
    • 继承类
    • 代码
  • 常见情况
    • 报错提示
    • 解决方法
    • 属性作用
    • 封装
    • 继承
    • 多态

前言

上两篇文章已经通过静态方法和this扩展方式,实现了倒计时公共代码的封装。
通过代码的封装,不仅代码减少了,也提高了代码的可维护性,一举多得,何乐不为。
这也是编程最有魅力的地方,随着编码经验的增多以及不停的学习,就会满满理解和领悟一些知识点,理论以及设计思想。

【C#】当重复使用一段代码倒计时时,使用普通类和静态方法,实现简单的封装性、可扩展性、可维护性

【C#】当重复使用一段代码倒计时时,使用静态类和静态方法,实现简单的this扩展方法

优化前

优化前,是通过在每个窗体添加一段倒计时异步方法代码,然后窗体界面添加一个label标签用于显示当前实时时间。

界面

在这里插入图片描述
在这里插入图片描述

代码

/// <summary>
/// 倒计时
/// </summary>
private void CurrentTime()
{Task.Run(() =>{while (true){lbTime.Text = $"当前时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";Thread.Sleep(1000);}});
}

优化后

这次优化是通过静态类静态方法实现,并且是使用this进行扩展。
同时把控件初始化位置以及高宽度大小设置成独立的变量成员,可对其进行赋值,否则使用默认值。

界面

在这里插入图片描述

继承类

实现类对接口类进行继承,从下面可以知道,实现类必须实现接口定义好的成员和方式,否则就会提示下面报错信息
在这里插入图片描述

代码

  • 封装方法
/// <summary>
/// 接口类,通过继承实现方法
/// 1)接口不能包含实例字段,比如:public int x;
/// </summary>
public interface ITimeLabel
{int X { get; set; }int Y { get; set; }int Width { get; set; }int Height { get; set; }void Get(Form that);
}public class TimeLabelClass : ITimeLabel
{public int X { get; set; } = 50;public int Y { get; set; } = 50;public int Width { get; set; } = 179;public int Height { get; set; } = 15;public void Get(Form that){Label label = new Label();label.Location = new Point() { X = X, Y = Y };label.Width = Width;label.Height = Height;that.Controls.Add(label);Task.Run(() => {while (true){label.Text = $"当前时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";Thread.Sleep(1000);}});}
}
  • 窗体1
    这里直接实例化后就调用方法,这样就是使用了默认位置和大小值
private void Test1_Load(object sender, EventArgs e)
{//TimeLabel.Time(this, 50, 50);//this.TimeLabel();new TimeLabelClass().Get(this);
}private void button1_Click(object sender, EventArgs e)
{Test2 test2 = new Test2();test2.Show();
}
  • 窗体2
    这里对位置和大小值进行了重新赋值,体现了封装的灵活性
private void Test2_Load(object sender, EventArgs e)
{ITimeLabel timeLabel = new TimeLabelClass();timeLabel.X = 20;timeLabel.Y = 20;timeLabel.Width = 139;timeLabel.Height = 12;timeLabel.Get(this);
}

常见情况

报错提示

在窗体异步方法里操作主线程控件时,会提示错误,线程间操作无限:从不不是创建控件"lbTime"的线程访问它。
在这里插入图片描述

解决方法

可在构造函数里增加下面代码

/// <summary>
/// 构造函数
/// </summary>
public TestTemp()
{InitializeComponent();CheckForIllegalCrossThreadCalls = false;
}

属性作用

CheckForIllegalCrossThreadCalls 可以拆分成 4 个词:
1.Check:检查
2.For:为了
3.Illegal:非法的
4.CrossThreadCalls:跨线程调用
整体意思是:为了检查跨线程调用是否非法。

C# 中的 CheckForIllegalCrossThreadCalls 是一个属性,用于检查在多线程编程中是否存在潜在的跨线程调用问题。
它可以帮助开发人员在开发过程中更好地处理线程间的通信。

在 C# 中,UI 线程是用于处理用户界面操作的主线程,而其他操作(如网络请求、计算等)通常需要在后台线程中执行。
然而,直接在后台线程中访问 UI 控件是不安全的,可能会导致不可预测的结果和操作系统错误。
CheckForIllegalCrossThreadCalls 属性的作用是在调试模式下,检测程序是否存在不安全的跨线程调用。

当该属性设置为 true 时,在出现跨线程调用时,会引发一个异常,以提醒开发人员进行相应的处理。
当属性设置为 false 时,不会引发异常,但仍然可能导致不安全的操作。

这个属性主要用于帮助开发人员及时发现并修复由于线程之间的错误调用而导致的问题。
它可以提高应用程序的稳定性和可靠性,避免潜在的线程安全问题。
要注意的是,这个属性只在调试模式下起作用,在发布版本中不会进行检查。

#三大特性
C# 面向对象的三大特性是封装、继承和多态。

封装

它是指将对象的某些内部状态和行为封装起来,只暴露必要的接口供其他对象使用,并且隐藏其实现细节,从而保证了对象的安全性和可维护性。
比如:内部类成员、私有成员、保护类成员等

继承

它是指通过继承一个已有的类来创建一个新类,新类继承了父类的属性和方法,并可以新增或重写一些方法,从而在代码复用和扩展性方面提供了便利。
比如:交通工具,不同汽车都有公共的属性年份和品牌等,不同品牌和年份的车价格不同,继承共有属性的同时也增加了属于自己的价格方法

多态

它是指同一种类型的对象,在不同的情况下,可以有不同的状态和行为。在面向对象编程中,多态通常通过继承和接口实现。
比如:都是动物,猫狗动物发出的声音不同

温故而知新,不同阶段重温知识点,会有不一样的认识和理解,博主将巩固一遍知识点,并以实践方式和大家分享,若能有所帮助和收获,这将是博主最大的创作动力和荣幸。也期待认识更多优秀新老博主。

这篇关于【C#】当重复使用一段代码倒计时时,定义接口类和通过实现类继承接口方式进行封装方法和体现代码灵活性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/609198

相关文章

Spring Retry 实现乐观锁重试实践记录

《SpringRetry实现乐观锁重试实践记录》本文介绍了在秒杀商品SKU表中使用乐观锁和MybatisPlus配置乐观锁的方法,并分析了测试环境和生产环境的隔离级别对乐观锁的影响,通过简单验证,... 目录一、场景分析 二、简单验证 2.1、可重复读 2.2、读已提交 三、最佳实践 3.1、配置重试模板

SpringBoot使用Jasypt对YML文件配置内容加密的方法(数据库密码加密)

《SpringBoot使用Jasypt对YML文件配置内容加密的方法(数据库密码加密)》本文介绍了如何在SpringBoot项目中使用Jasypt对application.yml文件中的敏感信息(如数... 目录SpringBoot使用Jasypt对YML文件配置内容进行加密(例:数据库密码加密)前言一、J

Java中有什么工具可以进行代码反编译详解

《Java中有什么工具可以进行代码反编译详解》:本文主要介绍Java中有什么工具可以进行代码反编译的相关资,料,包括JD-GUI、CFR、Procyon、Fernflower、Javap、Byte... 目录1.JD-GUI2.CFR3.Procyon Decompiler4.Fernflower5.Jav

Spring Boot 中正确地在异步线程中使用 HttpServletRequest的方法

《SpringBoot中正确地在异步线程中使用HttpServletRequest的方法》文章讨论了在SpringBoot中如何在异步线程中正确使用HttpServletRequest的问题,... 目录前言一、问题的来源:为什么异步线程中无法访问 HttpServletRequest?1. 请求上下文与线

解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题

《解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题》在Spring开发中,@Autowired注解常用于实现依赖注入,它可以应用于类的属性、构造器或setter方法上,然... 目录1. 为什么 @Autowired 在属性上被警告?1.1 隐式依赖注入1.2 IDE 的警告:

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

Python进行PDF文件拆分的示例详解

《Python进行PDF文件拆分的示例详解》在日常生活中,我们常常会遇到大型的PDF文件,难以发送,将PDF拆分成多个小文件是一个实用的解决方案,下面我们就来看看如何使用Python实现PDF文件拆分... 目录使用工具将PDF按页数拆分将PDF的每一页拆分为单独的文件将PDF按指定页数拆分根据页码范围拆分

javaScript在表单提交时获取表单数据的示例代码

《javaScript在表单提交时获取表单数据的示例代码》本文介绍了五种在JavaScript中获取表单数据的方法:使用FormData对象、手动提取表单数据、使用querySelector获取单个字... 方法 1:使用 FormData 对象FormData 是一个方便的内置对象,用于获取表单中的键值

Vue ElementUI中Upload组件批量上传的实现代码

《VueElementUI中Upload组件批量上传的实现代码》ElementUI中Upload组件批量上传通过获取upload组件的DOM、文件、上传地址和数据,封装uploadFiles方法,使... ElementUI中Upload组件如何批量上传首先就是upload组件 <el-upl