AI教我学编程之C#类的基本概念(1)
前言
在AI教我学编程之C#类型 中,我们学习了C#类型的的基础知识,而类正是类型的一种.
目录
-
区分类和类型
- 什么是类?
- 对话AI
- 追问
- 实操
-
追踪属性的使用
- AI登场
- 逐步推进
- 提出疑问
- 药不能停
- 终于实现
-
探索事件的使用
- 异步/交互操作
- 耗时操作
- 提示
-
总结
区分类和类型
在 C# 中,类是类型的一种。C# 是一种面向对象的编程语言,它的类型系统分为值类型和引用类型。类属于引用类型的范畴,因为它是用户定义的引用类型。
什么是类?
或者说,什么样的构造可以称之为类?
在菜鸟教程上我们可以看到这段话

我们来看看AI对此会如何回答?
对话AI
![]()
什么样的构造可以称之为类?
![]()
在面向对象编程中,一个类是一个用于创建对象的蓝图或模板。一个类可以包含以下元素:
-
成员变量(字段): 用于存储对象的状态或属性。
class Person {// 成员变量public string Name;public int Age; } -
成员方法: 用于定义对象的行为或操作。
class Person {// 成员方法public void DisplayInfo(){Console.WriteLine($"Name: {Name}, Age: {Age}");} } -
构造函数: 用于初始化对象的特定状态。
class Person {// 成员变量public string Name;public int Age;// 构造函数public Person(string name, int age){Name = name;Age = age;} } -
属性(可选): 提供对成员变量的访问和修改的公共接口。
class Person {// 自动属性public string Name { get; set; }public int Age { get; set; } } -
事件(可选): 允许对象发布和订阅事件。
class Button {// 事件public event EventHandler Click;// 触发事件的方法protected virtual void OnClick(EventArgs e){Click?.Invoke(this, e);} }
一个类的目的是封装数据和行为,通过创建对象的实例来使用这些数据和行为。上述元素的组合形成了一个完整的类定义。在使用类时,你可以实例化它并调用其中的方法,访问或修改成员变量等。
首先我们看到这几段代码都以class关键字作为开始,就是说,这段代码表示
类是由class关键字开始,名称为person,由以下三个元素组成
- 成员变量:
Name:用于存储人员的名字。Age:用于存储人员的年龄。
- 构造函数:
public Person(string name, int age):构造函数用于在创建Person类的实例时初始化对象的状态(名字和年龄)。 - 成员方法:
DisplayInfo():成员方法用于显示人员的名字和年龄信息。
那么剩下两个
可选项是做什么的呢?我们接着往下看
追问
![]()
你刚刚列出了两个可选项,属性和事件,为什么这两个只是可选项?
![]()
属性和事件在类的设计中是可选的,而不是必需的,这取决于你的设计需求。下面是关于为什么它们是可选项的一些解释:
-
属性(Properties):
- 作用: 属性提供了一种用于访问和修改类的成员变量的公共接口。它们允许你在读取或写入属性值时执行逻辑,并且可以隐藏实际的字段实现。
- 为何是可选: 有时,一个简单的公共字段足以满足类的需求,而不需要额外的逻辑。在这种情况下,你可以选择跳过属性的使用。
class Person {// 公共字段public string Name;public int Age; }或者使用属性:
class Person {// 属性public string Name { get; set; }public int Age { get; set; } } -
事件(Events):
- 作用: 事件允许类发布和订阅特定的行为,通常与异步编程和观察者模式有关。
- 为何是可选: 如果你的类不需要定义或响应外部的事件,那么你可以省略事件的使用。事件通常在需要处理异步或交互式操作时使用,而在其他情况下可能不是必需的。
class Button {// 事件public event EventHandler Click;// 触发事件的方法protected virtual void OnClick(EventArgs e){Click?.Invoke(this, e);} }
因此,可选性提供了灵活性,使得类的设计能够根据具体需求进行调整,而不必强制要求每个类都具有属性和事件。
为更加直观理解这两个概念,我们来实操一下
实操
1、打开Visual Studio (我的是2010,在这里就用2010来演示)

2、新建项目

3、模板选择visual C# Windows—> Windows窗体应用

4、起好名后进入以下页面
提示:千万别忘了命名规范 哦!

5、点击左侧边栏工具箱

6、我们看到工具箱把窗体覆盖住了

7、不用担心,点击工具箱右上角的倒三角,选择停靠,这样就可以正常显示了

8、选择工具箱中的工作控件“按钮”,拖动到窗体上

9、右击按钮,选择属性,我们可以在右下角看到属性栏

此时,不管我们拖动什么控件到窗体中,单击控件或者窗体,即可看它的属性

让我们回到刚刚的问题,为什么属性和事件是可选的?
AI的回答是:在不需要额外逻辑的情况下,可以跳过属性的使用
追踪属性的使用
1、双击按钮进入如下页面

AI登场
![]()
以上这段代码中,有个按钮,我需要根据这段代码实现点击按钮跳出"青青草原我最狂,舍我其谁懒大王!"的提示文字
![]()
要在点击按钮时弹出提示文字,你需要在 button1_Click 事件处理方法中添加相应的代码。以下是修改后的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace FirstProject
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){// 在按钮点击事件中添加代码MessageBox.Show("青青草原我最狂,舍我其谁懒大王!");}}
}
在这个修改后的代码中,当 button1 被点击时,button1_Click 事件处理方法会弹出一个消息框(MessageBox),显示指定的提示文字。 MessageBox.Show 方法用于在 Windows 窗体应用程序中显示一个简单的消息框。
如下图所示,点击debug旁边的绿色三角开启调试

画面左上角我们看到,项目正在运行

点击按钮,跳出提示

逐步推进
![]()
现在我需要你在代码中添加类的属性的使用
![]()
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace FirstProject
{public partial class Form1 : Form{// 新增的属性public string Name { get; set; }public int Age { get; set; }public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){// 在按钮点击事件中使用属性Name = "青青草原我最狂";Age = 25;// 弹出消息框显示属性值MessageBox.Show($"姓名:{Name}\n年龄:{Age}\n舍我其谁懒大王!");}}
}
在这个示例中,我添加了两个属性
Name和Age,并在按钮点击事件中给它们赋值。然后,通过MessageBox.Show方法显示属性的值。这个例子演示了如何在类中使用属性,以便存储和获取对象的状态。
提出疑问
![]()
这段代码中属性的使用是必须的吗?
![]()
在给定的代码示例中,属性的使用并不是必需的。在C#中,属性是用于封装对象的状态并提供对其进行访问和修改的公共接口的一种方式。在一些情况下,你可能不需要使用属性,尤其是当类的成员变量(字段)可以直接访问而不需要额外的逻辑时。
在给定的代码示例中,如果你只是在按钮点击事件中使用了一次 Name 和 Age,并且没有其他需要对这些值进行封装或加入逻辑的地方,那么使用属性是可选的。你可以直接在 button1_Click 事件中声明局部变量来存储这些值,而无需将它们定义为属性。
以下是示例,演示如何在不使用属性的情况下直接声明并使用局部变量:
using System;
using System.Windows.Forms;namespace FirstProject
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){// 直接声明和使用局部变量string name = "青青草原我最狂";int age = 25;// 弹出消息框显示变量值MessageBox.Show($"姓名:{name}\n年龄:{age}\n舍我其谁懒大王!");}}
}
在这个例子中,我直接在 button1_Click 事件中声明了局部变量 name 和 age,并使用它们存储和显示信息,而没有使用属性。
药不能停
紧接着我补充道
![]()
我需要你添加的是必需的属性,根据原有代码重新添加
![]()
如果你希望使用属性,我会在代码中重新添加必需的属性。以下是在原有代码基础上添加必需的属性的修改版本:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace FirstProject
{public partial class Form1 : Form{// 必需的属性public string Name { get; set; }public int Age { get; set; }public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){// 在按钮点击事件中使用属性Name = "青青草原我最狂";Age = 25;// 弹出消息框显示属性值MessageBox.Show($"姓名:{Name}\n年龄:{Age}\n舍我其谁懒大王!");}}
}
在这个修改后的代码中,我添加了两个名为 Name 和 Age 的属性。这样,你可以在类的其他地方使用这些属性,而不仅仅是在 button1_Click 事件中。这种封装的方式提高了代码的可维护性和灵活性。
终于实现
![]()
根据现有代码写两段代码,第一段代码即原代码,另一段代码则必须使用属性才能实现其逻辑和功能
![]()
代码段一:不使用属性,直接声明并使用局部变量
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace FirstProject
{public partial class Form1 : Form{// 必需的属性public string Name { get; set; }public int Age { get; set; }public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){// 在按钮点击事件中使用属性Name = "青青草原我最狂";Age = 25;// 弹出消息框显示属性值MessageBox.Show($"姓名:{Name}\n年龄:{Age}\n舍我其谁懒大王!");}}
}
代码段二:使用属性实现逻辑和功能
在这个示例中,我添加了一些逻辑和功能,并使用属性来存储和访问数据:
using System;
using System.Windows.Forms;namespace FirstProject
{public partial class Form1 : Form{// 使用属性public string Name { get; set; }public int Age { get; set; }public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){// 使用属性存储数据Name = "青青草原我最狂";Age = 25;// 调用带有逻辑的方法DisplayInfo();// 弹出消息框显示属性值MessageBox.Show($"姓名:{Name}\n年龄:{Age}\n舍我其谁懒大王!");}// 带有逻辑的方法private void DisplayInfo(){Console.WriteLine($"在 DisplayInfo 方法中:姓名:{Name},年龄:{Age}");// 可以在这里添加更多的逻辑和功能}}
}
在这个示例中,button1_Click 事件使用属性 Name 和 Age 存储数据,然后调用了一个带有逻辑的方法 DisplayInfo。在这个方法中,你可以添加更多的逻辑和功能。这种方式充分利用了属性的封装性,使得逻辑更加清晰和可维护。
这里的DisplayInfo方法,就是AI刚刚提到的可以填充额外的逻辑的地方
探索事件的使用
异步/交互操作
![]()
我现在需要在原代码中可以”处理异步或交互式操作“,据此要求完善代码
![]()
如果你想要在原有代码中处理异步或交互式操作,可以使用异步方法和
async/await关键字。下面是对原有代码的修改,使其能够处理异步操作:
using System;
using System.Threading.Tasks;
using System.Windows.Forms;namespace FirstProject
{public partial class Form1 : Form{// 使用属性public string Name { get; set; }public int Age { get; set; }public Form1(){InitializeComponent();}private async void button1_Click(object sender, EventArgs e){// 使用属性存储数据Name = "青青草原我最狂";Age = 25;// 异步操作await DisplayInfoAsync();// 弹出消息框显示属性值MessageBox.Show($"姓名:{Name}\n年龄:{Age}\n舍我其谁懒大王!");}// 异步方法private async Task DisplayInfoAsync(){// 异步操作,模拟耗时操作await Task.Delay(2000);// 在异步方法中使用属性Console.WriteLine($"在 DisplayInfoAsync 方法中:姓名:{Name},年龄:{Age}");// 可以在这里添加更多的异步操作}}
}
在这个示例中,我将 DisplayInfo 方法改为 DisplayInfoAsync,并在其内部添加了一个异步操作 await Task.Delay(2000) 以模拟耗时操作。同时,button1_Click 事件也被标记为 async,并在其中使用了 await 关键字来等待异步方法的完成。这样,你可以在异步方法中执行可能涉及等待的耗时操作,而不会阻塞主线程。
耗时操作
![]()
在你刚才给出的代码中,可以执行哪些”耗时操作“,告诉我,并且将这个操作添加到代码中,使我在调试时可以明显的看到”耗时“这一效果
![]()
在我之前提供的代码示例中,我添加了一个模拟耗时操作的异步方法
DisplayInfoAsync,其中使用了await Task.Delay(2000)来模拟一个持续两秒的异步操作。这个延迟操作是一个简单的例子,用来模拟可能的耗时操作。
在实际的应用中,你可以将异步方法中的 Task.Delay 替换为真实的耗时操作,比如从数据库中读取数据、进行网络请求、进行复杂的计算等。以下是对代码的修改,其中包含了一个更具体的耗时操作示例:
using System;
using System.Threading.Tasks;
using System.Windows.Forms;namespace FirstProject
{public partial class Form1 : Form{// 使用属性public string Name { get; set; }public int Age { get; set; }public Form1(){InitializeComponent();}private async void button1_Click(object sender, EventArgs e){// 使用属性存储数据Name = "青青草原我最狂";Age = 25;// 调用带有耗时操作的异步方法await DisplayInfoWithDelayAsync();// 弹出消息框显示属性值MessageBox.Show($"姓名:{Name}\n年龄:{Age}\n舍我其谁懒大王!");}// 带有耗时操作的异步方法private async Task DisplayInfoWithDelayAsync(){Console.WriteLine("开始执行耗时操作...");// 模拟从数据库中读取数据,等待2秒钟await Task.Delay(2000);// 在异步方法中使用属性Console.WriteLine($"在 DisplayInfoWithDelayAsync 方法中:姓名:{Name},年龄:{Age}");Console.WriteLine("耗时操作完成。");}}
}
在这个修改后的代码中,我添加了一段输出,用于在控制台中显示耗时操作的开始和结束。当你点击按钮时,可以在输出中看到开始和结束的标志,这段时间模拟了耗时操作的执行时间。在实际应用中,你可以将这里的 Task.Delay 替换为你真实的耗时操作。
提示
以上代码在VS2010中不可用,在VS2019及以上中可用
VS2010

VS2019

开启调试后,我们点击按钮

两秒钟后,跳出提示

总结
又是仓促的一天,现在上传的这个版本有些瑕疵,明天我会补好,感谢各位的阅读,喜欢本文的话,点赞收藏关注支持一下博主吧!感谢厚爱!
回到顶部
相关文章:
AI教我学编程之C#类的基本概念(1)
前言 在AI教我学编程之C#类型 中,我们学习了C#类型的的基础知识,而类正是类型的一种. 目录 区分类和类型 什么是类? 对话AI 追问 实操 追踪属性的使用 AI登场 逐步推进 提出疑问 药不能停 终于实现 探索事件的使用 异步/交互操作 耗时操…...
前端js 数据结构:对象 object、数组Array 、Map 的创建、增删改 / 遍历数据
目录 前端js 数据结构:对象、数组、Map 的使用1 对象(object)1.1 创建对象1.1.1 对象字面量(最常用): {}1.1.2 使用 new 关键字和对象构造函数1.1.3 Object.create() 1.2 修改对象1.2.1 直接赋值:对象的属性名直接赋值1.2.2 点号/…...
ARM_Linux的NFS网络文件系统的搭建
介绍: NFS是network filesystem的简称,可以不同的主机通过网络访问远端的NFS服务器共享出来的文件,这样主机通过网络访问NFS服务器,我们就可以在开发板上通过网络访问主机的文件。 为什么要使用NFS网络文件呐? 1、传…...
vscode配置web开发环境(WampServer)
这里直接去下载了集成的服务器组件wampserver,集成了php,MySQL,Apache 可能会出现安装问题,这里说只有图上这些VC包都安装了才能继续安装,进入报错里提供的链接 在页面内搜索相关信息 github上不去可以去镜像站 下载…...
00-Rust前言
问:为什么要近期想学习Rust? 答: Rust出来也是有一段时间了,从Microsoft吵着要重构他们的C"祖传代码"开始,Rust就披着“高效,安全”的头衔。而自己决定要学习Rust,是因为近期发现:涉…...
3.conda的使用
anaconda安装 ubuntu 安装conda 系统架构 uname -m打开终端,不启动base conda config --set auto_activate_base falseconda命令使用 1.查看conda版本 conda --version2.查看conda配置环境 conda config --show3.设置镜像 #设置清华镜像 conda config --add…...
IPv6自动隧道---6to4中继
6to4中继 普通IPv6网络需要与6to4网络通过IPv4网络互通,这可以通过6to4中继路由器方式实现。所谓6to4中继,就是通过6to4隧道转发的IPv6报文的目的地址不是6to4地址,但转发的下一跳是6to4地址,该下一跳为路由器我们称之为6to4中继。隧道的IPv4目的地址依然从下一跳的6to4地…...
低代码开发:解锁数字化转型新维度
在信息化浪潮中,企业正面临着前所未有的挑战与机遇。一方面,市场环境瞬息万变,业务需求迭代频繁,对快速应用开发提出了更高要求;另一方面,传统软件开发模式受限于高成本、长周期等瓶颈,难以满足…...
写一个定时备份数据库的脚本,且只保留最近3天
下面是一个备份数据库并只保留最近3天备份的脚本示例,该脚本使用Python编写: import os import datetime import shutil # 更多源码前往获取:www.qqmu.com # 数据库备份目录 backup_dir "/path/to/backupdir"# 数据库名称 databa…...
java常见面试题:请详细解释如何在Java EE应用中添加EJB
在Java EE应用中添加EJB(Enterprise JavaBeans)涉及几个关键步骤。下面是一个详细的解释: 创建EJB项目: 首先,你需要创建一个Java EE项目。这通常通过IDE(如Eclipse、IntelliJ IDEA等)完成&…...
视频监控需求记录
记录一下最近要做的需求,我个人任务还是稍微比较复杂的 需求:需要实现一个视频实时监控、视频回放、视频设备管理,以上都是与组织架构有关 大概的界面长这个样子 听着需求好像很简单,但是~我们需要在一个界面上显示两个厂商的视…...
Self-RAG:通过自我反思学习检索、生成和批判
论文地址:https://arxiv.org/abs/2310.11511 项目主页:https://selfrag.github.io/ Self-RAG学习检索、生成和批评,以提高 LM 的输出质量和真实性,在六项任务上优于 ChatGPT 和检索增强的 LLama2 Chat。 问题:万能L…...
C++基于多态的职工管理系统(附代码下载)
🌈个人主页:godspeed_lucip 🔥 系列专栏:C从基础到进阶 本文配套markdown文件、配套完整程序(vs项目,可直接运行)网盘链接请翻阅至文章最底部获取。 职工管理系统🌏1、管理系统需求…...
Java安全 CC链1分析
Java安全之CC链1分析 什么是CC链环境搭建jdk下载idea配置创建项目 前置知识Transformer接口ConstantTransformer类invokerTransformer类ChainedTransformer类 构造CC链1CC链1核心demo1demo1分析 寻找如何触发CC链1核心TransformedMap类AbstractInputCheckedMapDecorator类readO…...
Miracast手机高清投屏到电视(免费)
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Miracast概述 Miracast是一种无线显示标准,它允许支持Miracast的设备之间通过Wi-Fi直接共享音频和视频内容,实现屏幕镜像或扩展显示。这意味着你可以…...
【elementUI】el-select相关问题
官方使用DEMO <template><el-select v-model"value" placeholder"请选择"><el-optionv-for"item in options":key"item.value":label"item.label":value"item.value"></el-option></…...
【蓝桥杯日记】复盘第一篇——顺序结构
🚀前言 本期是一篇关于顺序结构的题目的复盘,通过复盘基础知识,进而把基础知识学习牢固!通过例题而进行复习基础知识。 🚩目录 前言 1.字符三角形 分析: 知识点: 代码如下 2. 字母转换 题目分析: 知…...
使用 MinIO 和 PostgreSQL 简化数据事件
本教程将教您如何使用 Docker 和 Docker Compose 在 MinIO 和 PostgreSQL 之间设置和管理数据事件,也称为存储桶或对象事件。 您可能已经在利用 MinIO 事件与外部服务进行通信,现在您将通过使用 PostgreSQL 自动化和简化数据事件管理来增强数据处理能力…...
苹果电脑(Mac)的node版本安装以及升降级
在开发过程中,对于不同的开发环境或者较老的项目可能需要切换不同的node版本,此过程会涉及到node版本的升级与降级,安装node版本管理模块n(sudo命令)。 全局安装n模块 sudo npm install n -g//输入后回车,…...
WCP知识分享平台的容器化部署
1. 什么是WCP? WCP是一个知识管理、分享平台,支持针对文档(包括pdf,word,excel等)进行实时解析、索引、查询。 通过WCP知识分享平台进行知识信息的收集、维护、分享。 通过知识创建、知识更新、知识检索、知识分享、知识评价、知识统计等功能进行知识生命周期管理。 wcp官…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
Pydantic + Function Calling的结合
1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...
