【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
文章目录
- 一、万物之父(`object`)
- 1、万物之父:`System.Object`
- 2、`System.Object` 的作用
- 二、装箱 和 拆箱
- 1、装箱(Boxing)
- 2、拆箱(Unboxing)
- 3、示例:装箱
- 4、示例:拆箱
- 5、装箱与拆箱的性能问题
- 6、优缺点
- 6、总结
- 三、`sealed` 密封类
- 1、语法:
- 2、为什么使用密封类?
- 3、示例:密封类的使用
- 4、密封类与虚拟方法(`virtual`)
- 5、总结
- 专栏推荐
- 完结
一、万物之父(object
)
1、万物之父:System.Object
在 C# 中,所有类型(无论是值类型
还是引用类型
)都是直接或间接从 System.Object
类派生的。也就是说,System.Object
是所有类型的基类,提供了所有对象的基础功能。object
(小写)是 C# 语言的一个关键字,是对 System.Object 类型的别名。
object
是所有类型的基类,他本质是一个类(引用类型)
2、System.Object
的作用
-
可以利用里氏替换原则,用object容器装所有对象
object obj = new Player(); if (obj is Player) { (obj as Player).PlayerAtk(); }
-
可以用于表示不确定类型,作为函数参数类型等
public class Example { public static void Main() { int number = 42; // 由于所有类型都继承自 System.Object,我们可以将 int 类型的变量赋值给 object 类型的变量 object obj = number; Console.WriteLine(obj.ToString()); // 输出:42 } }
在这个示例中,尽管 number
是 int
类型(值类型),我们还是能够将其赋给 Object
类型的变量。这是因为 int
是从 System.Object
派生的。
二、装箱 和 拆箱
1、装箱(Boxing)
- 定义:当
值类型
(如int
、struct
等)被隐式或显式转换为引用类型
(通常是object
或接口
(接口的知识后面会介绍))时,CLR
会在堆上创建一个新的对象,并将值类型的数据复制到该对象中。 - 性能影响:每次装箱都会分配新的内存并进行数据复制,这会带来额外的开销。
2、拆箱(Unboxing)
- 定义:当
引用类型
被显式转换回原始的值类型
时,CLR
会从堆上的对象中复制数据回到栈上的值类型。 - 性能影响:拆箱同样涉及数据复制,也会有性能开销。
ps
:CLR 是 Common Language Runtime(公共语言运行时)的缩写,它是 .NET Framework 的核心组件之一。CLR 负责管理代码的执行,提供各种服务来确保应用程序的安全性、可靠性和性能。
3、示例:装箱
int number = 42;
// 装箱,将值类型 int 转换为引用类型 object
object obj = number;
Console.WriteLine(obj); // 输出:42
在上述代码中,number
是 int
类型的值类型,赋值给 obj
后,发生了装箱。此时 obj
实际上指向一个存储 42
的堆内存区域。
4、示例:拆箱
object obj = 42; // 装箱:将值类型 int 转换为对象
int number = (int)obj; // 拆箱:将对象类型的值提取为值类型
Console.WriteLine(number); // 输出:42
在这段代码中,obj
是一个 object
类型的引用,实际上它包含了一个 int
类型的值。通过拆箱,我们将 obj
转换回 int
类型,并将其赋值给 number
。
5、装箱与拆箱的性能问题
装箱和拆箱操作会涉及额外的内存分配和数据复制,特别是在频繁进行装箱和拆箱的场景下,可能会导致性能瓶颈。因此,通常在性能要求较高的场合中,应该避免
不必要的装箱和拆箱操作。
6、优缺点
- 好处:不确定类型时可以方便参数的存储和传递
- 坏处:存在内存迁移,增加性能消耗
6、总结
理解装箱和拆箱对于 C# 的性能优化非常重要,尤其是在涉及到大量数据处理和集合操作时,避免不必要的
装箱拆箱能够显著提升程序的性能。不是不用,尽量少用。
三、sealed
密封类
在 C# 中,密封类(sealed class
)是指一个不能被继承的类。通过将一个类声明为密封类,意味着其他类不能从它派生出子类。这在某些情况下非常有用,例如你希望确保一个类的实现不被修改或扩展时。
1、语法:
要将一个类声明为密封类,使用 sealed
关键字:
public sealed class MyClass
{
public void MyMethod()
{
Console.WriteLine("Hello, World!");
}
}
2、为什么使用密封类?
- 防止继承:通过将类标记为密封类,可以防止其他类继承该类。这可以确保类的行为不会被修改,从而增加代码的安全性和稳定性。
- 性能优化:密封类可以让编译器进行更优化的处理,因为它知道该类不能被继承。这在某些情况下可以提高性能,尤其是在虚拟方法调用方面。
- 设计意图明确:密封类可以明确表明设计者的意图,表示这个类是最终的实现,不打算让它扩展。
3、示例:密封类的使用
using System;
public sealed class SealedClass
{
public void DisplayMessage()
{
Console.WriteLine("This is a sealed class!");
}
}
public class Program
{
public static void Main()
{
SealedClass sc = new SealedClass();
sc.DisplayMessage();
// 尝试继承 SealedClass 会引发编译错误
// public class DerivedClass : SealedClass { } // 编译错误: 'SealedClass' cannot be inherited.
}
}
在上面的代码中,SealedClass
是一个密封类,无法被继承。如果你尝试创建一个从 SealedClass
派生的类,会引发编译时错误。
4、密封类与虚拟方法(virtual
)
密封类常常与 虚拟方法 一起使用,目的是防止方法被重写。
virtual
关键字用于在基类中声明一个方法为虚方法。详细知识会在后面C#面向对象动态多态里再介绍。
例如,如果一个类是密封的,那么它的虚拟方法就不能被子类重写:
public sealed class SealedClass
{
public virtual void DisplayMessage()
{
Console.WriteLine("Message from the sealed class.");
}
}
// 这段代码会出错,因为 SealedClass 是密封类,无法被继承
// public class DerivedClass : SealedClass
// {
// public override void DisplayMessage() { } // 编译错误
// }
如果 SealedClass
没有 sealed
关键字,它的虚拟方法 DisplayMessage
可以被派生类重写。但由于它是密封的,无法被继承,所以该方法就无法被重写了。
5、总结
sealed
关键字用于定义一个密封类,阻止其他类继承该类。- 密封类可以提高代码的安全性和稳定性,避免不必要的继承。
- 密封类通常用于希望完全控制行为,防止扩展或重写的场景。
专栏推荐
地址 |
---|
【从零开始入门unity游戏开发之——C#篇】 |
【从零开始入门unity游戏开发之——unity篇】 |
【制作100个Unity游戏】 |
【推荐100个unity插件】 |
【实现100个unity特效】 |
【unity框架开发】 |
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~