news 2026/3/31 21:19:52

C#之类型与实例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C#之类型与实例

C# 类与实例教程:从基础到高级应用

类是 C# 面向对象编程的核心概念,它允许我们创建自定义类型,封装数据和行为。

1. 类的基本概念

1.1 什么是类?

类是创建对象的蓝图或模板,它定义了对象的:

  • 数据(字段/属性):对象的状态
  • 行为(方法):对象可以执行的操作
  • 事件:对象可以响应的通知
  • 嵌套类型:类中定义的其他类、结构体等

1.2 简单类示例

// 定义一个简单的 Person 类publicclassPerson{// 字段(数据成员)privatestringname;privateintage;// 构造函数publicPerson(stringname,intage){this.name=name;this.age=age;}// 方法(行为)publicvoidIntroduce(){Console.WriteLine($"Hello, my name is{name}and I'm{age}years old.");}}

2. 创建实例(对象)

2.1 实例化类

使用new关键字创建类的实例:

// 创建 Person 类的实例Personperson1=newPerson("Alice",30);Personperson2=newPerson("Bob",25);// 调用方法person1.Introduce();// 输出: Hello, my name is Alice and I'm 30 years old.person2.Introduce();// 输出: Hello, my name is Bob and I'm 25 years old.

2.2 对象生命周期

  1. 实例化:分配内存并调用构造函数
  2. 使用:通过实例访问成员
  3. 垃圾回收:当没有引用指向对象时,GC 自动回收内存

3. 类成员详解

3.1 字段(Fields)

类的变量成员,通常声明为private

publicclassBankAccount{privatedecimalbalance;// 字段publicvoidDeposit(decimalamount){balance+=amount;}}

3.2 属性(Properties)

提供对字段的安全访问,通常包含getset访问器:

publicclassBankAccount{privatedecimalbalance;// 属性publicdecimalBalance{get{returnbalance;}privateset{balance=value;}// 限制只能在类内部设置}// 自动实现的属性(简化写法)publicstringAccountNumber{get;privateset;}publicBankAccount(stringaccountNumber){AccountNumber=accountNumber;}}

3.3 方法(Methods)

定义对象的行为:

publicclassCalculator{// 实例方法publicintAdd(inta,intb){returna+b;}// 静态方法(属于类而非实例)publicstaticdoubleSquareRoot(doublex){returnMath.Sqrt(x);}}// 使用Calculatorcalc=newCalculator();intsum=calc.Add(5,3);// 调用实例方法doubleroot=Calculator.SquareRoot(16);// 调用静态方法

3.4 构造函数(Constructors)

初始化对象状态的特殊方法:

publicclassCar{publicstringModel{get;}publicintYear{get;}// 默认构造函数publicCar(){Model="Unknown";Year=DateTime.Now.Year;}// 带参数的构造函数publicCar(stringmodel,intyear){Model=model;Year=year;}// 构造函数链publicCar(stringmodel):this(model,DateTime.Now.Year){}}

3.5 析构函数(Destructors)

(C# 中更常用IDisposable模式)

publicclassResourceHolder:IDisposable{privatebooldisposed=false;// 实现 IDisposablepublicvoidDispose(){Dispose(true);GC.SuppressFinalize(this);}protectedvirtualvoidDispose(booldisposing){if(!disposed){if(disposing){// 释放托管资源}// 释放非托管资源disposed=true;}}// 析构函数(备用)~ResourceHolder(){Dispose(false);}}

4. 访问修饰符

控制类成员的可访问性:

修饰符同一类同一程序集派生类其他程序集
public
private
protected
internal
protected internal✗ (除非也是派生类)

5. 高级特性

5.1 静态类

不能被实例化,只能包含静态成员:

publicstaticclassMathUtilities{publicstaticreadonlydoublePi=3.14159;publicstaticintFactorial(intn){if(n<=1)return1;returnn*Factorial(n-1);}}// 使用doublearea=MathUtilities.Pi*5*5;intfact=MathUtilities.Factorial(5);

5.2 分部类(Partial Classes)

将类定义分散在多个文件中:

// File1.cspublicpartialclassEmployee{publicstringFirstName{get;set;}publicstringLastName{get;set;}}// File2.cspublicpartialclassEmployee{publicstringFullName=>$"{FirstName}{LastName}";publicvoidPrintInfo(){Console.WriteLine($"Employee:{FullName}");}}

5.3 嵌套类

在类内部定义另一个类:

publicclassOuterClass{privateintouterValue=10;publicclassNestedClass{publicvoidPrintOuterValue(OuterClassouter){// Console.WriteLine(outerValue); // 错误,不能直接访问Console.WriteLine(outer.outerValue);// 需要通过外部类实例访问}}}// 使用OuterClassouter=newOuterClass();OuterClass.NestedClassnested=newOuterClass.NestedClass();nested.PrintOuterValue(outer);

5.4 记录类型(Record,C# 9.0+)

不可变的数据类型,简化值语义:

publicrecordPersonRecord(stringFirstName,stringLastName);// 使用PersonRecordp1=new("Alice","Smith");PersonRecordp2=p1with{LastName="Johnson"};// 创建修改后的副本Console.WriteLine(p1==p2);// 输出: False (值比较)

5.5 结构体 vs 类

特性结构体
类型引用类型值类型
继承支持不支持
默认构造函数必须显式定义编译器提供默认构造函数
内存分配栈(通常)
适用场景复杂对象小型数据结构

6. 完整示例

usingSystem;namespaceClassDemo{// 定义一个完整的类publicclassStudent{// 字段privatestringname;privateintage;privatereadonlystringstudentId;// 只读字段,只能在构造函数中设置// 自动实现的属性publicdoubleGPA{get;privateset;}// 带验证的属性privatestring_major;publicstringMajor{get=>_major;set{if(!string.IsNullOrWhiteSpace(value)){_major=value;}else{Console.WriteLine("Invalid major specified!");}}}// 构造函数publicStudent(stringname,intage,stringstudentId){this.name=name;this.age=age;this.studentId=studentId;this.GPA=0.0;this.Major="Undeclared";}// 实例方法publicvoidUpdateGPA(doublenewGrade){// 简化计算,实际应考虑学分权重GPA=(GPA*(CoursesTaken-1)+newGrade)/CoursesTaken;}// 只读属性(计算属性)publicintCoursesTaken{get;}=0;// 静态成员publicstaticintTotalStudents{get;privateset;}=0;publicStudent():this("Unknown",18,GenerateStudentId()){TotalStudents++;}// 静态构造函数(初始化静态成员)staticStudent(){Console.WriteLine("Student class initialized");}// 静态方法privatestaticstringGenerateStudentId(){return$"STU{DateTime.Now.Ticks%100000:D5}";}// 方法重载publicvoidEnroll(stringcourseName){Console.WriteLine($"{name}enrolled in{courseName}");}publicvoidEnroll(stringcourseName,intcredits){Console.WriteLine($"{name}enrolled in{courseName}({credits}credits)");}// 对象方法publicoverridestringToString(){return$"{name}(ID:{studentId}), Age:{age}, Major:{Major}, GPA:{GPA:F2}";}}classProgram{staticvoidMain(string[]args){// 创建实例Studentalice=newStudent("Alice",20,"STU00123");Studentbob=newStudent();// 使用默认构造函数// 访问成员alice.Major="Computer Science";alice.UpdateGPA(3.5);alice.Enroll("C# Programming",4);bob.Major="";// 会触发验证bob.Major="Mathematics";bob.UpdateGPA(3.8);bob.Enroll("Advanced Calculus");// 输出信息Console.WriteLine(alice);Console.WriteLine(bob);Console.WriteLine($"Total students:{Student.TotalStudents}");}}}

7. 最佳实践

  1. 封装性:将字段设为private,通过属性暴露
  2. 不可变性:考虑使用readonly字段或记录类型
  3. 命名规范:类名使用 PascalCase,方法名使用 PascalCase
  4. 单一职责:每个类应该只有一个明确的职责
  5. 构造函数初始化:确保对象在创建后处于有效状态
  6. 文档注释:使用 XML 注释说明公共成员
  7. 避免过度设计:从简单类开始,根据需要添加复杂性
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/31 20:13:24

SSH X11 forwarding运行图形界面程序

SSH X11 Forwarding 运行图形界面程序 在人工智能和数据科学的日常开发中&#xff0c;一个常见的场景是&#xff1a;你有一台部署在云端或数据中心的高性能服务器&#xff0c;它没有显示器、键盘和鼠标&#xff0c;但你需要在这台“黑盒”机器上运行带有图形界面的工具——比如…

作者头像 李华
网站建设 2026/3/31 20:13:22

判断两个IP是否属于同一子网_判断是否在同一个子网

判断两个IP地址是否属于同一个子网&#xff08;网段&#xff09;的方法 判断两个IPv4地址是否在同一个子网的核心原理是&#xff1a;将每个IP地址与子网掩码进行按位与&#xff08;AND&#xff09;运算&#xff0c;得到网络地址&#xff08;网络号&#xff09;。如果两个网络地…

作者头像 李华
网站建设 2026/3/31 20:13:21

转换wps字符串

LET(文本,SUBSTITUTE(D1,CHAR(10),","),长度,LEN(文本),结果,REDUCE("",SEQUENCE(长度),LAMBDA(累计值,i,LET(字符,MID(文本,i,1),编码,CODE(字符),IF(编码<128,累计值&字符,LET(最后一个字符,IF(累计值"","",RIGHT(累计值,1))…

作者头像 李华
网站建设 2026/3/30 1:22:42

Linux lsof命令查看Miniconda占用的端口资源

使用 lsof 精准排查 Miniconda 环境中的端口占用问题 在现代 AI 与数据科学开发中&#xff0c;Python 已经成为事实上的标准语言。从 Jupyter Notebook 到 PyTorch 训ing 脚本&#xff0c;再到基于 Flask 或 FastAPI 的模型服务部署&#xff0c;几乎每个环节都离不开 Python 生…

作者头像 李华
网站建设 2026/3/31 12:45:33

科研级Python环境搭建:Miniconda镜像确保实验结果可复现

科研级Python环境搭建&#xff1a;Miniconda镜像确保实验结果可复现 在人工智能和数据科学领域&#xff0c;一个令人沮丧的场景屡见不鲜&#xff1a;几个月前还能完美运行的实验代码&#xff0c;如今却在导入时抛出奇怪的错误——“module torch has no attribute utils.data&a…

作者头像 李华
网站建设 2026/3/28 19:44:49

使用cookiecutter生成Miniconda项目模板

使用 cookiecutter 生成 Miniconda 项目模板 在数据科学与机器学习团队中&#xff0c;一个常见的场景是&#xff1a;新成员入职第一天&#xff0c;被分配到一个 GitHub 仓库链接和一份“环境配置说明”文档。接下来的几小时甚至一整天&#xff0c;他们都在折腾 Python 版本、包…

作者头像 李华