【从零开始入门unity游戏开发之——C#篇21】C#面向对象的封装——`this`扩展方法、运算符重载、内部类、`partial` 定义分部类
文章目录
- 一、`this`扩展方法
- 1、扩展方法的基本语法
- 2、使用扩展方法
- 3、扩展方法的注意事项
- 5、扩展方法的限制
- 6、总结
- 二、运算符重载
- 1、C# 运算符重载
- 2、运算符重载的基本语法
- 3. 示例:重载加法运算符 (`+`)
- 4、使用重载的运算符
- 5、支持重载的运算符
- 6、不能重载的运算符
- 7、运算符重载的注意事项
- 8、总结
- 三、内部类
- 1、**示例:**
- 2、**特点:**
- 四、`partial` 定义分部类
- 1、**示例:**
- 2、**使用:**
- 3、**特点:**
- 专栏推荐
- 完结
一、this
扩展方法
扩展方法是 C# 的一项强大特性,它允许你为现有类型(包括系统类型或第三方库中的类型)添加方法,而不需要修改其源代码或继承该类型。扩展方法通常用于增强类的功能,特别是当你无法修改类本身时。
扩展方法的语法非常简单,但它们实际上是静态方法
,只是通过特殊的语法“看起来”像是实例方法。
1、扩展方法的基本语法
扩展方法需要满足以下条件:
- 必须是 静态方法。
- 必须在 静态类 中定义。
- 第一个参数是要扩展的类型,且该参数前面需要加上
this
关键字。
示例:
public static class StringExtensions
{// 扩展方法:为 string 类型添加 Log 方法public static void Log(this string str){Console.WriteLine($"打印:str");}
}
在上面的例子中,我们为 string
类型添加了一个 Log
方法,打印字符串。
2、使用扩展方法
定义了扩展方法后,可以像调用实例方法一样,直接通过扩展类型的实例调用它们。
class Program
{static void Main(){string str = "Hello, World!";str.Log();}
}
上面的代码中,我们通过 str.Log()
调用了 string
类型的扩展方法 Log
,这看起来就像 string
类型原本就有这个方法一样。
结果
3、扩展方法的注意事项
-
命名空间:扩展方法必须在
using
指令引入其定义所在的命名空间后才能使用。例如,假设StringExtensions
类位于MyExtensions
命名空间下,那么使用时需要引入该命名空间:using MyExtensions;// 然后可以直接使用扩展方法
-
静态方法:虽然扩展方法表现得像实例方法,但它们实际上是静态方法。编译器会将扩展方法的调用转换为相应的静态方法调用。
-
优先级:扩展方法的优先级通常高于实例方法,因此,如果某个类型已经实现了与扩展方法同名的方法,实例方法会优先被调用。
-
不可重写:扩展方法无法覆盖类型的现有方法。例如,如果你为
string
类型扩展了一个Reverse
方法,它不会覆盖string
类型的原始方法或其他扩展方法。
5、扩展方法的限制
虽然扩展方法非常强大,但它们有一些局限性和注意事项:
- 无法访问私有成员:扩展方法只能访问公共和保护成员,不能访问目标类型的私有成员。
- 会导致命名冲突:如果多个扩展方法使用相同的名称并且作用于相同的类型,就可能引起命名冲突。可以通过限定命名空间来解决这种问题。
- 不支持扩展构造函数:扩展方法只能扩展已有的实例方法,不能添加构造函数、字段或事件。
6、总结
扩展方法是 C# 中非常有用的特性,能够通过增加新的方法而不修改现有类型的代码来增强功能。它们适用于添加一些工具方法、帮助函数等,特别是在不能直接修改类代码的情况下。
- 扩展方法定义在静态类中,并且需要使用
this
关键字来标记目标类型。 - 使用扩展方法时,需要确保引入其定义所在的命名空间。
- 扩展方法虽然在语法上像实例方法,但其实是静态方法。
二、运算符重载
1、C# 运算符重载
在 C# 中,运算符重载允许你为自定义类型(类或结构体)定义特定的运算符行为。通过运算符重载,你可以使自定义类型像内建类型(例如 int
或 double
)一样使用运算符进行操作。运算符重载是通过重写某些运算符的方法来实现的。
2、运算符重载的基本语法
运算符重载方法必须是 静态方法,并且需要使用关键字 operator
来定义。它的基本语法如下:
public static <返回类型> operator <运算符>(<类型1> 参数1, <类型2> 参数2)
{// 你的运算符实现逻辑
}
3. 示例:重载加法运算符 (+
)
假设我们有一个表示二维坐标的 Point
类型,我们希望为其重载 +
运算符,使得两个 Point
对象可以相加。
public class Point
{public int X { get; set; }public int Y { get; set; }// 构造函数public Point(int x, int y){X = x;Y = y;}// 重载加法运算符 (+)public static Point operator +(Point p1, Point p2){return new Point(p1.X + p2.X, p1.Y + p2.Y);}
}
在这个例子中,+
运算符被重载为将两个 Point
对象的 X
和 Y
坐标分别相加。
4、使用重载的运算符
重载运算符之后,你可以像操作内建类型一样操作 Point
类型:
public class Program
{public static void Main(){Point p1 = new Point(2, 3);Point p2 = new Point(5, 7);Point result = p1 + p2; // 使用重载的 + 运算符Console.WriteLine($"({result.X}, {result.Y})"); // 输出 (7, 10)}
}
在这里,p1 + p2
实际上调用了 Point
类型中定义的 operator +
方法,返回一个新的 Point
对象,X
和 Y
分别相加。
5、支持重载的运算符
- 算术运算符:
+
,-
,*
,/
,%
- 关系运算符:
==
,!=
,<
,>
,<=
,>=
- 位运算符:
&
,|
,^
,<<
,>>
- 单目运算符:
+
(一元加),-
(一元减),++
,--
- 其他运算符:
[]
(索引器)、()
,~
(按位取反)、true
,false
,!
(逻辑非)、is
,as
6、不能重载的运算符
- 逻辑运算符:
&&
,||
7、运算符重载的注意事项
-
必须是静态方法:运算符重载方法必须是静态的,因此无法访问实例成员(除非通过参数传入)。
-
返回值类型:运算符重载方法必须返回运算结果的类型。例如,
+
运算符应返回加法结果,==
运算符应返回一个bool
类型的值。 -
重载
==
和!=
时需要保持一致性:如果你重载了==
运算符,通常也需要重载!=
运算符,以确保逻辑一致。 -
运算符的优先级和结合性不能改变:C# 不允许改变运算符的优先级或结合性。你只能指定运算符的行为,而无法改变它们的优先级。
-
建议只在必要时重载运算符:虽然运算符重载非常强大,但过多或不当的使用可能会导致代码的可读性变差。应该仅在自然语义上支持运算符操作时才重载它们。
8、总结
- 运算符重载是通过静态方法来实现的。
- 重载时应保持逻辑的一致性,尤其是
==
和!=
。 - 过度使用运算符重载可能会导致代码可读性降低,因此应适度使用。
三、内部类
内部类 是定义在另一个类或结构体内部的类。它通常用于实现封装,或者当一个类的功能仅在另一个类的上下文中有意义时,使用内部类可以增加代码的组织性和可维护性。内部类的访问权限可以是 public
、private
、protected
等,因此它可以根据需求暴露或隐藏给外部使用。
1、示例:
public class OuterClass
{// 外部类的字段private int outerField = 10;// 定义内部类public class InnerClass{// 内部类可以访问外部类的成员public void Display(){OuterClass outer = new OuterClass();Console.WriteLine("外部类的字段值: " + outer.outerField);}}
}class Program
{static void Main(){// 创建内部类的实例OuterClass.InnerClass inner = new OuterClass.InnerClass();inner.Display();}
}
2、特点:
- 内部类可以访问外部类的所有成员(包括私有成员)。
- 内部类可以作为外部类的一个组成部分,或者是外部类的一个辅助工具。
- 内部类的生命周期通常是由外部类来管理的。
四、partial
定义分部类
分部类 是指一个类的定义可以分散到多个文件中,这样有助于将一个庞大的类拆分成多个小的部分进行维护。partial
关键字用于声明类是分部类,编译器会在编译时将这些不同的部分合并成一个完整的类。
1、示例:
假设你有两个文件 Class1.Part1.cs
和 Class1.Part2.cs
,它们都属于同一个类 Class1
:
- Class1.Part1.cs:
public partial class Class1
{public void Method1(){Console.WriteLine("Method1 from Part1");}
}
- Class1.Part2.cs:
public partial class Class1
{public void Method2(){Console.WriteLine("Method2 from Part2");}
}
2、使用:
class Program
{static void Main(){Class1 obj = new Class1();obj.Method1(); // 来自 Part1obj.Method2(); // 来自 Part2}
}
3、特点:
- 分部类使得一个类可以被分布在多个文件中,这对于大型项目非常有用。
- 各个部分可以在不同的代码文件中定义,但它们会被视为同一个类。
partial
类的不同部分可以放在不同的命名空间或文件中,只要它们在同一项目中即可。- 各个部分的访问修饰符、方法和属性都可以独立指定,但它们最终会被合并为一个类。
专栏推荐
地址 |
---|
【从零开始入门unity游戏开发之——C#篇】 |
【从零开始入门unity游戏开发之——unity篇】 |
【制作100个Unity游戏】 |
【推荐100个unity插件】 |
【实现100个unity特效】 |
【unity框架开发】 |
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
相关文章:

【从零开始入门unity游戏开发之——C#篇21】C#面向对象的封装——`this`扩展方法、运算符重载、内部类、`partial` 定义分部类
文章目录 一、this扩展方法1、扩展方法的基本语法2、使用扩展方法3、扩展方法的注意事项5、扩展方法的限制6、总结 二、运算符重载1、C# 运算符重载2、运算符重载的基本语法3. 示例:重载加法运算符 ()4、使用重载的运算符5、支持重载的运算符6、不能重载的运算符7、…...

Java进程占用的内存有哪些部分?
大家好,我是锋哥。今天分享关于【Java进程占用的内存有哪些部分?】面试题。希望对大家有帮助; Java进程占用的内存有哪些部分? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Java进程在运行时,会将内存划分为多个区域…...
【华为OD机试真题】【2024年E卷】数值同化-队列BFS(C++/Java/Python)
文章目录 分值:200题目描述思路复杂度分析AC 代码 分值:200 题目描述 存在一个 m * n 的 二维数组只,其成员取值范围为0, 1, 2。其中值为1的元素具备同化特性,每经过1S,将上下左右值为0的元素同化为1。而值为2的元素…...
“魔法糖果盒的秘密:用朴素贝叶斯算法猜糖果颜色”
想象一下,你有一个神奇的糖果盒,这个糖果盒里有两种糖果:红色的和蓝色的。你闭上眼睛,从盒子里拿出一个糖果,然后尝一尝,你想知道这个糖果是红色的还是蓝色的。朴素贝叶斯算法就像是一个魔法规则࿰…...
linux中docker命令大全
基本命令 docker pull 拉取镜像 docker pull docker push 推送镜像到DockerRegistry docker push docker images 查看本地镜像 docker images docker rmi 删除本地镜像 docker rmi docker run 创建并运行容器(不能重复创建) docker run d…...
Python `str.strip()` 的高级用法详解
Python str.strip 的高级用法详解 1. str.strip() 的基本用法2. str.strip() 的高级用法2.1 移除指定字符2.2 移除多个指定字符2.3 移除换行符和制表符2.4 结合正则表达式的高级处理 3. lstrip() 和 rstrip() 的用法3.1 lstrip():移除左端字符3.2 rstrip()ÿ…...

[蓝桥杯 2019 国 B] 排列数
目录 前言 题解 思路 疑问 解答 前言 对于本篇文章是站在别人的基础之上来写的,对于这道题作为2019年国赛B组的最难的一题,他的难度肯定是不小的,这道题我再一开始接触的时候连思路都没有,也是看了两三遍别人发的题解&#x…...
[bug] StarRocks borker load意向之外的bug
意向之外,又清理之中 背景: StarRocks各方面碾压相同类型的数据库,最近我们要从生成HIVE导历史数据(ORC格式)到StarRocks,前期小测一下,在测试是没问题,上生产先导2个月的数据&…...
2025年前端面试热门题目——HTML|CSS|Javascript|TS知识
以下是对这些 HTML 面试问题的详细解答: 1. HTML 的 src 和 href 属性有什么区别? src (Source) 属性: 用于嵌入资源,例如图像、脚本或 iframe。加载资源时,当前页面的加载会暂停,直到资源加载完成。常用于 <img&g…...

Linux中部署项目
1.下载JDK17 进入 /usr/local 目录,创建 java 文件夹。并将 JDK17 上传到 java 目录下。 上传成功后,通过cd命令进入Java文件夹目录,解压 JDK17 压缩包,命令 unzip zulu17.44.53-ca-jdk17.0.8.1-linux_x64.zip。 如果报错说 u…...
在 CentOS 上安装 MySQL 8
在 CentOS 上安装 MySQL 8 您可以按照以下步骤操作: 1. 更新系统 首先,更新系统软件包以确保安装的最新版本。 sudo yum update -y 2. 安装 MySQL 8 安装 MySQL 存储库 wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.r…...
gradle项目下载依赖报错
报错信息 Cannot resolve external dependency org.projectlombok:lombok:1.18.36 because no repositories are defined. Required by:project :Possible solution:- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/…...
solon 集成 activemq-client (sdk)
原始状态的 activemq-client sdk 集成非常方便,也更适合定制。就是有些同学,可能对原始接口会比较陌生,会希望有个具体的示例。 <dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-client&l…...
LRU 缓存
LRU 缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否…...

使用ZLMediaKit 开源项目搭建RTSP 服务器
ZLMediaKit 是啥? ZLMediaKit是国人开发的开源C流媒体服务器,同SRS一样是主流的流媒体服务器。 ZLToolKit是基于C11的高性能服务器框架,和ZLMediaKit是同一个作者,ZLMediaKit正是使用该框架开发的。 官网 ZLMediaKit开源地址&…...
数组晨考2day08
1.用一句话描述数组 在内存中 一块连续的空间 存储相同类型的数据 长度是固定的 2.数组各个类型的默认值 整数:0 浮点:0.0 布尔:false 字符:\u0000 其他:null 3.Arrays类toString,copyOf,sort&a…...

《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》简介
《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》已于近日上市,该书由北京大学出版社出版。距离第1版上市已经过去二年半多。本文希望与读者朋友们分享下这本书里面的大致内容。 封面部分 首先是介绍封面部分。 《鸿蒙HarmonyOS应用开发从入门…...

麒麟操作系统服务架构保姆级教程(二)sersync、lsync备份和NFS持久化存储
如果你想拥有你从未拥有过的东西,那么你必须去做你从未做过的事情 上篇文章我们说到rsync虽好,但是缺乏实时性,在实际应用中,咱们可以将rsync写进脚本,然后写进定时任务去备份,如果每天凌晨1:00…...

将OBJ或GLB文件转换为3DTiles
格式简介 GLB文件(.GLB)代表“GL传输格式二进制文件”,是用于共享3D数据的标准化文件格式。确切地说,它可以包含有关三维模型、场景、模型、光源、材质、节点层次和动画的信息。 OBJ文件是一种文本文件格式,这就意味…...
Flink DataStream API 编程指南
(对于Flink的开发,建议使用Java,Scala的支持未来会被移除) DataStream是什么 DataStream API得名于DataStream这个Java类,可以将它们视为可以包含重复项的不可变数据集合。该数据可以是有限的,也可以是无限的,用于处理它们的API是相同的。 DataStream在用法上和普通的…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...