当前位置: 首页 > article >正文

【从零开始入门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
        }
    }
    

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

二、装箱 和 拆箱

1、装箱(Boxing)

  • 定义:当值类型(如 intstruct 等)被隐式或显式转换为引用类型(通常是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

在上述代码中,numberint 类型的值类型,赋值给 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

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


http://www.kler.cn/a/448214.html

相关文章:

  • Leetcode中最常用的Java API——util包
  • iterm2 focus时灰色蒙层出现的解决办法
  • 秒优科技-供应链管理系统 login/doAction SQL注入漏洞复现
  • 基于微信小程序的乡村旅游系统
  • Redis常见阻塞原因总结
  • 国家认可的人工智能从业人员证书如何报考?
  • 日拱一卒(19)——leetcode学习记录:两个子序列的最大点积
  • java开发入门学习五-流程控制
  • 新版国标GB28181设备端Android版EasyGBD支持国标GB28181-2022,支持语音对讲,支持位置上报,开源在Github
  • mysql冷知识
  • 【CSS in Depth 2 精译_089】15.2:CSS 过渡特效中的定时函数
  • 飞牛 fnos 使用docker部署Easyimage2图床 方便上传和管理图片
  • 国家认可的人工智能从业人员证书如何报考?
  • linux定时器操作
  • 牛客网 SQL37查找多列排序
  • OpenWRT——官方镜像安装Docker(网络环境需设置)并配置Sun-Panel
  • 贪心算法解决分发糖果问题
  • 【Express】用express搭建本地服务器(轻松上手)
  • CSS系列(20)-- 自定义属性详解
  • 动态头部:利用注意力机制统一目标检测头部
  • 前端笔试面试题目——数据结构和算法篇(一)
  • 云手机能用来干什么?云手机在跨境电商领域的用途
  • SSM 架构上的 Vue 电脑测评系统:彰显科技评测魅力
  • XMLHttpRequest接受chunked编码传输的HTTP Response时有问题
  • 力扣第110题:平衡二叉树
  • MVVM、MVC、MVP 的区别