AI教我学编程之C#类的基本概念(1)

前言

在AI教我学编程之C#类型 中,我们学习了C#类型的的基础知识,而正是类型的一种.

目录

  • 区分类和类型

    • 什么是类?
    • 对话AI
    • 追问
    • 实操
  • 追踪属性的使用

    • AI登场
    • 逐步推进
    • 提出疑问
    • 药不能停
    • 终于实现
  • 探索事件的使用

    • 异步/交互操作
    • 耗时操作
    • 提示
  • 总结

区分类和类型

在 C# 中,类是类型的一种。C# 是一种面向对象的编程语言,它的类型系统分为值类型和引用类型。类属于引用类型的范畴,因为它是用户定义的引用类型。

什么是类?

或者说,什么样的构造可以称之为类?
在菜鸟教程上我们可以看到这段话
在这里插入图片描述
我们来看看AI对此会如何回答?

对话AI

程序员

什么样的构造可以称之为类?

在这里插入图片描述

在面向对象编程中,一个类是一个用于创建对象的蓝图或模板。一个类可以包含以下元素:

  1. 成员变量(字段): 用于存储对象的状态或属性。

    class Person
    {// 成员变量public string Name;public int Age;
    }
    
  2. 成员方法: 用于定义对象的行为或操作。

    class Person
    {// 成员方法public void DisplayInfo(){Console.WriteLine($"Name: {Name}, Age: {Age}");}
    }
    
  3. 构造函数: 用于初始化对象的特定状态。

    class Person
    {// 成员变量public string Name;public int Age;// 构造函数public Person(string name, int age){Name = name;Age = age;}
    }
    
  4. 属性(可选): 提供对成员变量的访问和修改的公共接口。

    class Person
    {// 自动属性public string Name { get; set; }public int Age { get; set; }
    }
    
  5. 事件(可选): 允许对象发布和订阅事件。

    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():成员方法用于显示人员的名字和年龄信息。

那么剩下两个可选项是做什么的呢?我们接着往下看

追问

程序员

你刚刚列出了两个可选项,属性和事件,为什么这两个只是可选项?

在这里插入图片描述

属性和事件在类的设计中是可选的,而不是必需的,这取决于你的设计需求。下面是关于为什么它们是可选项的一些解释:

  1. 属性(Properties):

    • 作用: 属性提供了一种用于访问和修改类的成员变量的公共接口。它们允许你在读取或写入属性值时执行逻辑,并且可以隐藏实际的字段实现。
    • 为何是可选: 有时,一个简单的公共字段足以满足类的需求,而不需要额外的逻辑。在这种情况下,你可以选择跳过属性的使用。
    class Person
    {// 公共字段public string Name;public int Age;
    }
    

    或者使用属性:

    class Person
    {// 属性public string Name { get; set; }public int Age { get; set; }
    }
    
  2. 事件(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舍我其谁懒大王!");}}
}

在这个示例中,我添加了两个属性 NameAge,并在按钮点击事件中给它们赋值。然后,通过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 事件使用属性 NameAge 存储数据,然后调用了一个带有逻辑的方法 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
在这里插入图片描述
开启调试后,我们点击按钮

在这里插入图片描述
两秒钟后,跳出提示
在这里插入图片描述

总结

又是仓促的一天,现在上传的这个版本有些瑕疵,明天我会补好,感谢各位的阅读,喜欢本文的话,点赞收藏关注支持一下博主吧!感谢厚爱!
回到顶部

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/411340.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【前后端的那些事】评论功能实现

文章目录 聊天模块1. 数据库表2. 后端初始化2.1 controller2.2 service2.3 dao2.4 mapper 3. 前端初始化3.1 路由创建3.2 目录创建3.3 tailwindCSS安装 4. tailwindUI5. 前端代码编写 前言:最近写项目,发现了一些很有意思的功能,想写文章&…

前端——框架——Vue

提示: 本文只是从宏观角度简要地梳理一遍vue3,不至于说学得乱七八糟、一头雾水、不知南北,如果要上手写代码、撸细节,可以根据文中的关键词去查找资料 简问简答: vue.js是指vue3还是vue2? Vue.js通常指的是…

回馈科教,非凸科技助力第48届ICPC亚洲区决赛

1月12日-14日,“华为杯”第48届国际大学生程序设计竞赛(ICPC)亚洲区决赛在上海大学成功举办。非凸科技作为此次赛事的支持方之一,希望携手各方共同推动计算机科学和技术的发展。 这是一场智慧的巅峰对决,320支优秀队伍…

K8s-架构

一、K8s节点划分 K8s集群包含Master(控制节点)和Node(工作节点),应用部署在Node节点上。 集群架构图: 二、Master节点 Master节点分成四个组件:scheduler、ApiServer、Controller Manager、ETCD。类似三层结构,controller&#…

20240117-【UNITY 学习】增加墙跑功能和跳墙功能

替换脚本PlayerCam_01.cs using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening;public class PlayerCam_02 : MonoBehaviour {// 视觉灵敏度参数public float sensX 400;public float sensY 400;// 视角垂直旋转角度限制publ…

redis安装-Linux为例

可以下载一个Shell或者MobaXterm工具,便于操作 在redis官网下载压缩包 开始安装 安装依赖 yum install -y gcc tcl切换目录 切换目录后直接把redis安装包拖到/user/local/src/下 cd /user/local/src/解压然后安装 #解压 tar -zxvf redis-7.2.4.tar.gz #安装 …

Kafka-消费者-KafkaConsumer分析-ConsumerNetworkClient

前面介绍过NetworkClient的实现,它依赖于KSelector、InFlightRequests、Metadata等组件,负责管理客户端与Kafka集群中各个Node节点之间的连接,通过KSelector法实现了发送请求的功能,并通过一系列handle*方法处理请求响应、超时请求…

阿里云云原生助力安永创新驱动力实践探索

云原生正在成为新质生产力变革的核心要素和企业创新的数字基础设施。2023 年 12 月 1 日,由中国信通院举办的“2023 云原生产业大会”在北京召开。在大会“阿里云云原生”专场,安永科技咨询合伙人王祺分享了对云原生市场的总览及趋势洞见,及安…

React的合成事件

合成事件:通过事件委托,利用事件传播机制,当事件传播到document时,再进行分发到对应的组件,从而触发对应所绑定的事件,然后事件开始在组件树DOM中走捕获冒泡流程。 原生事件 —— > React事件 —— >…

小白准备蓝桥杯之旅(c/c++b组)

前言:省赛获奖比例高达百分之60,只要比一半的人努力,你就能大概率获奖。 寒假做的3件事 1.稳基础 熟练掌握基础语法部分,c比c多个stl库优势,c语言的同学需要会实现c中stl库部分 2.刷真题 大概比赛前30天,坚持每天做…

QQ文档删除了怎么恢复?记住这3个方法!

我们有时会因为误操作或者需要清理空间而删除一些不需要的文件,包括我们在QQ平台上接收的文档。但是,一旦我们删除了这些文档,如果没有备份的情况下就难以找回。 那么,如果我们在删除QQ文档后想要恢复它们,应该怎么做…

HarmonyOS —— buildMode 设置(对比 Android Build Varient)

前言 在安卓中 Build Variant 主要依赖模块(module)中 build.gradle 的 BuildType 和 ProductFlavor 提供的属性和方法,我们可以使用 Build Type 可以配置不同的构建方式、ProductFlavor 主要用来进行多渠道打包。 在鸿蒙中要做到同样像效果…