【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类

文章目录

一、万物之父(object

1、万物之父:System.Object

在 C# 中,所有类型(无论是值类型还是引用类型)都是直接或间接从 System.Object 类派生的。也就是说,System.Object 是所有类型的基类,提供了所有对象的基础功能。object(小写)是 C# 语言的一个关键字,是对 System.Object 类型的别名。

object是所有类型的基类,他本质是一个类(引用类型)

2、System.Object 的作用

  • 可以利用里氏替换原则,用object容器装所有对象

    csharp 复制代码
    object obj = new Player();
    if (obj is Player)
    {
        (obj as Player).PlayerAtk();
    }
  • 可以用于表示不确定类型,作为函数参数类型等

    csharp 复制代码
    public class Example
    {
        public static void Main()
        {
            int number = 42;
            
            // 由于所有类型都继承自 System.Object,我们可以将 int 类型的变量赋值给 object 类型的变量
            object obj = number;
            
            Console.WriteLine(obj.ToString());  // 输出:42
        }
    }

在这个示例中,尽管 numberint 类型(值类型),我们还是能够将其赋给 Object 类型的变量。这是因为 int 是从 System.Object 派生的。

二、装箱 和 拆箱

1、装箱(Boxing)

  • 定义 :当值类型(如 intstruct 等)被隐式或显式转换为引用类型(通常是object接口接口的知识后面会介绍 ))时,CLR会在堆上创建一个新的对象,并将值类型的数据复制到该对象中。
  • 性能影响:每次装箱都会分配新的内存并进行数据复制,这会带来额外的开销。

2、拆箱(Unboxing)

  • 定义 :当引用类型被显式转换回原始的值类型时,CLR会从堆上的对象中复制数据回到栈上的值类型。
  • 性能影响:拆箱同样涉及数据复制,也会有性能开销。

ps:CLR 是 Common Language Runtime(公共语言运行时)的缩写,它是 .NET Framework 的核心组件之一。CLR 负责管理代码的执行,提供各种服务来确保应用程序的安全性、可靠性和性能。

3、示例:装箱

csharp 复制代码
int number = 42;

// 装箱,将值类型 int 转换为引用类型 object
object obj = number;

Console.WriteLine(obj);  // 输出:42

在上述代码中,numberint 类型的值类型,赋值给 obj 后,发生了装箱。此时 obj 实际上指向一个存储 42 的堆内存区域。

4、示例:拆箱

csharp 复制代码
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 关键字:

csharp 复制代码
public sealed class MyClass
{
    public void MyMethod()
    {
        Console.WriteLine("Hello, World!");
    }
}

2、为什么使用密封类?

  • 防止继承:通过将类标记为密封类,可以防止其他类继承该类。这可以确保类的行为不会被修改,从而增加代码的安全性和稳定性。
  • 性能优化:密封类可以让编译器进行更优化的处理,因为它知道该类不能被继承。这在某些情况下可以提高性能,尤其是在虚拟方法调用方面。
  • 设计意图明确:密封类可以明确表明设计者的意图,表示这个类是最终的实现,不打算让它扩展。

3、示例:密封类的使用

csharp 复制代码
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#面向对象动态多态里再介绍。

例如,如果一个类是密封的,那么它的虚拟方法就不能被子类重写:

csharp 复制代码
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

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

相关推荐
信号处理学渣7 分钟前
matlab画图,选择性显示legend标签
开发语言·matlab
红龙创客8 分钟前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
jasmine s17 分钟前
Pandas
开发语言·python
装不满的克莱因瓶30 分钟前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗37 分钟前
常用类晨考day15
java
biomooc38 分钟前
R 语言 | 绘图的文字格式(绘制上标、下标、斜体、文字标注等)
开发语言·r语言
骇客野人40 分钟前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
black^sugar42 分钟前
纯前端实现更新检测
开发语言·前端·javascript
404NooFound1 小时前
Python轻量级NoSQL数据库TinyDB
开发语言·python·nosql
用余生去守护2 小时前
python报错系列(16)--pyinstaller ????????
开发语言·python