【从零开始入门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(); // 来自 Part1
obj.Method2(); // 来自 Part2
}
}
3、特点:
- 分部类使得一个类可以被分布在多个文件中,这对于大型项目非常有用。
- 各个部分可以在不同的代码文件中定义,但它们会被视为同一个类。
partial
类的不同部分可以放在不同的命名空间或文件中,只要它们在同一项目中即可。- 各个部分的访问修饰符、方法和属性都可以独立指定,但它们最终会被合并为一个类。
专栏推荐
地址 |
---|
【从零开始入门unity游戏开发之——C#篇】 |
【从零开始入门unity游戏开发之——unity篇】 |
【制作100个Unity游戏】 |
【推荐100个unity插件】 |
【实现100个unity特效】 |
【unity框架开发】 |
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~