【从零开始入门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# 中,运算符重载允许你为自定义类型(类或结构体)定义特定的运算符行为。通过运算符重载,你可以使自定义类型像内建类型(例如 intdouble)一样使用运算符进行操作。运算符重载是通过重写某些运算符的方法来实现的。

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 对象的 XY 坐标分别相加。

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 对象,XY 分别相加。

5、支持重载的运算符

  • 算术运算符+, -, *, /, %
  • 关系运算符==, !=, <, >, <=, >=
  • 位运算符&, |, ^, <<, >>
  • 单目运算符+ (一元加),- (一元减),++, --
  • 其他运算符[] (索引器)、(), ~ (按位取反)、true, false, ! (逻辑非)、is, as

6、不能重载的运算符

  • 逻辑运算符&&, ||

7、运算符重载的注意事项

  • 必须是静态方法:运算符重载方法必须是静态的,因此无法访问实例成员(除非通过参数传入)。

  • 返回值类型:运算符重载方法必须返回运算结果的类型。例如,+ 运算符应返回加法结果,== 运算符应返回一个 bool 类型的值。

  • 重载 ==!= 时需要保持一致性:如果你重载了 == 运算符,通常也需要重载 != 运算符,以确保逻辑一致。

  • 运算符的优先级和结合性不能改变:C# 不允许改变运算符的优先级或结合性。你只能指定运算符的行为,而无法改变它们的优先级。

  • 建议只在必要时重载运算符:虽然运算符重载非常强大,但过多或不当的使用可能会导致代码的可读性变差。应该仅在自然语义上支持运算符操作时才重载它们。

8、总结

  • 运算符重载是通过静态方法来实现的。
  • 重载时应保持逻辑的一致性,尤其是 ==!=
  • 过度使用运算符重载可能会导致代码可读性降低,因此应适度使用。

三、内部类

内部类 是定义在另一个类或结构体内部的类。它通常用于实现封装,或者当一个类的功能仅在另一个类的上下文中有意义时,使用内部类可以增加代码的组织性和可维护性。内部类的访问权限可以是 publicprivateprotected 等,因此它可以根据需求暴露或隐藏给外部使用。

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.csClass1.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

一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

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

相关文章

android EditText密码自动填充适配

android上的密码&#xff08;其实不仅仅是密码&#xff0c;可以是用户名也可以是邮箱&#xff09;自动填充&#xff0c;是需要考虑适配的。 官方文档&#xff1a;https://developer.android.com/identity/autofill/autofill-optimize?hlzh-cn 什么是自动填充 手机厂商一般会…

stm32制作CAN适配器5--WinUsb上位机编写

上次我们要stm32制作了一个基于winusb有canfd适配器&#xff0c;今天我们来制作一个上位机程序来进行报文收发。 上位机还是用以前写好的&#xff0c;只是更改下dll文件。 项目链接器&#xff0c;输入&#xff0c;附加依赖项中增加winusb.lib winusb初始化&#xff1a;#incl…

数据库管理系统——数据库设计

摘要&#xff1a;本博客讲解了数据库管理系统中的数据库设计相关内容&#xff0c;包括概念结构设计&#xff1a;E-R模型&#xff0c;逻辑结构设计&#xff1a;E-R模型到关系设计等内容。 目录 一、数据库设计和数据模型 1.1.数据库设计概述 1. 2.数据库结构概述 1.3.数据库…

Pytorch | 从零构建AlexNet对CIFAR10进行分类

Pytorch | 从零构建AlexNet对CIFAR10进行分类 CIFAR10数据集AlexNet网络结构技术创新点性能表现影响和意义 AlexNet结构代码详解结构代码代码详解特征提取层 self.features分类部分self.classifier前向传播forward 训练过程和测试结果代码汇总alexnet.pytrain.pytest.py CIFAR1…

C++ 杨辉三角 - 力扣(LeetCode)

点击链接即可产看题目&#xff1a;118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 一、题目 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出…

【JetPack】WorkManager笔记

WorkManager简介&#xff1a; WorkManager 是 Android Jetpack 库中的一个重要组件。它用于处理那些需要在后台可靠执行的任务&#xff0c;这些任务可以是一次性的&#xff0c;也可以是周期性的&#xff0c;甚至是需要满足特定条件才执行的任务。例如&#xff0c;它可以用于在后…

GTID详解

概念和组成 1&#xff0c;全局事务表示&#xff1a;global transaction identifiers 2, GTID和事务一一对应&#xff0c;并且全局唯一 3&#xff0c;一个GTID在一个服务器上只执行一次 4&#xff0c;mysql 5.6.5开始支持 组成 GTID server_uuid:transaction_id 如&#xf…

常耀斌:深度学习和大模型原理与实战(深度好文)

目录 机器学习 深度学习 Transformer大模型架构 人工神经元网络 卷积神经网络 深度学习是革命性的技术成果&#xff0c;有利推动了计算机视觉、自然语言处理、语音识别、强化学习和统计建模的快速发展。 深度学习在计算机视觉领域上&#xff0c;发展突飞猛进&#xff0c;…

vsCode怎么使用vue指令快捷生成代码

1.下载Vetur插件 2.在文件-首选项-配置代码片段中找到vue.json文件 &#xff08;注&#xff1a;旧版本的编辑器路径为文件-首选项-用户片段&#xff09; 3.在打开的配置代码片段弹窗中搜索vue.json&#xff0c;找到并打开 &#xff08;注&#xff1a;如果搜不到的话就按住鼠标…

python学opencv|读取图像(十八)使用cv2.line创造线段

【1】引言 前序已经完成了opencv基础知识的学习&#xff0c;我们已经掌握了处理视频和图像的基本操作。相关文章包括且不限于&#xff1a; python学opencv|读取图像&#xff08;三&#xff09;放大和缩小图像_python(1)使用opencv读取并显示图像;(2)使用opencv对图像进行缩放…

unity webgl部署到iis报错

Unable to parse Build/WebGLOut.framework.js.unityweb! The file is corrupt, or compression was misconfigured? (check Content-Encoding HTTP Response Header on web server) iis报错的 .unityweb application/octet-stream iis中添加 MIME类型 .data applicatio…

【深度学习】零基础介绍循环神经网络(RNN)

RNN介绍 零基础介绍语言处理技术基本介绍分词算法词法分析工具文本分类与聚类情感分析 自然语言处理词向量词向量学习模型1. 神经网络语言模型2. CBOW 和 skip-gram3. 层次化softmax方法4. 负采样方法 RNN介绍RNN的变种&#xff1a;LSTM1. Forget Gate2. Input Gate3. Update M…

Docker Compose 安装 Harbor

我使用的系统是rocky Linux 9 1. 准备环境 确保你的系统已经安装了以下工具&#xff1a; DockerDocker ComposeOpenSSL&#xff08;用于生成证书&#xff09;#如果不需要通过https连接的可以不设置 1.1 安装 Docker 如果尚未安装 Docker&#xff0c;可以参考以下命令安装&…

面试题整理9----谈谈对k8s的理解1

谈谈对k8s的理解 1. Kubernetes 概念 1.1 Kubernetes是什么 Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;方便进行声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统&#xff0c;其服务、支持和工具的…

【JAVA】JAVA接口公共返回体ResponseData封装

一、JAVA接口公共返回体ResponseData封装&#xff0c;使用泛型的经典 例子 public class ResponseData<T> implements Serializable { /** * */ private static final long serialVersionUID 7098362967623367826L; /** * 响应状态码 */ …

Redis分片集群学习总结

Redis分片集群学习总结 为什么要使用分片集群&#xff1f;分片集群搭建Redis集群怎么写入读取数据呢&#xff1f;集群写入数据和读取数据怎么定位到对应的节点呢&#xff1f;怎么让多个数据写入同一个节点&#xff1f; 故障转移主从集群和分片集群使用场景 为什么要使用分片集群…

代理模式(JDK,CGLIB动态代理,AOP切面编程)

代理模式是一种结构型设计模式&#xff0c;它通过一个代理对象作为中间层来控制对目标对象的访问&#xff0c;从而增强或扩展目标对象的功能&#xff0c;同时保持客户端对目标对象的使用方式一致。 代理模式在Java中的应用,例如 1.统一异常处理 2.Mybatis使用代理 3.Spring…

入侵他人电脑,实现远程控制(待补充)

待补充 在获取他人无线网网络密码后&#xff0c;进一步的操作是实现入侵他人电脑&#xff0c;这一步需要获取对方的IP地址并需要制作自己的代码工具自动化的开启或者打开对方的远程访问权限。 1、获取IP地址&#xff08;通过伪造的网页、伪造的Windows窗口、hook&#xff0c;信…

windows安装Elasticsearch及增删改查操作

1.首先去官网下载Elasticsearch 下载地址 我这里选择的是7.17.18 选择windows版本 下载完成后解压是这样的 下载完成后点击elasticsearch.bat启动elasticsearch服务 输入http://localhost:9200看到如下信息说明启动成功。 还有记得修改elasticsearch.yml文件&#xff0c;…

aws(学习笔记第十九课) 使用ECS和Fargate进行容器开发

aws(学习笔记第十九课) 使用ECS和Fargate进行容器开发 学习内容&#xff1a; 使用本地EC2中部署docker应用使用ECS的EC2模式进行容器开发使用ECS的Fargate模式进行容器开发 1. 使用本地EC2中部署docker应用 docker整体 这里展示了docker的整体流程。 开发阶段 编写dockerfile…