也说new
也说new
今天看到了Anytao的[你必须知道的.NET] 第五回:深入浅出关键字---把new说透。Anytao这一系列文章写得都非常好,其实甚至正是我一直想写的。比起各种应用层面上的技巧,我更喜欢研究.NET的底层机制。但是光顾了自己研究了,也没好好写东西给大家分享。
《把new说透》这篇文章介绍的内容不错,但Anytao文字上可能没有表达得很清晰。C# 2.0中关键字new有三种作用——1)作为修饰符覆盖父类中的virtual成员,2)作为运算符创建对象,3)作为泛型类型中对类型形参的约束。
new的这三种功能其实是完全不相干的,Anders Liu个人感觉作为文章来说,应该完全分开在不同的小节中去介绍。
1 new修饰符
new修饰符用于修饰类型成员(属性、方法等)。
(懒得画图写代码了,所以采用纯文字描述。大家可以看Anytao的代码)
当父类中编写了virtual方法时,子类出现了相同签名的方法时,必须冠以override或new运算符。
如果使用override运算符,则可以实现“多态”。即:将子类对象转成父类型后,调用virtual方法,实际上执行的是子类中的方法代码。
而如果使用new运算符,则不会出现上述情况,将子类对象转成父类型后,调用virtual方法,实际上执行的是还是父类中的方法代码。
2 new运算符
new运算符用于创建对象。当使用new运算符创建对象时,会发生下列事情:
- 根据元数据中的类型信息,计算对象所需空间,根据值类型/引用类型的区别,在栈或者堆中开辟适当大小的存储区域。
- 根据元数据中的类型信息,对类成员空间进行排列。并初始化成员。(*)
- 调用构造器。
- 返回对象引用。
所以,string s = new string("asdf");实际上是首先根据string类型信息在堆上开辟存储空间,排列其成员,然后调用string(string s)签名的构造器,最后返回新对象引用,并通过等号赋给变量s。
因此,Anytao提到的int i与int i = new int()的区别也就出来了。
但这里Anytao没有陈述清楚的是,int i出现的位置——int i即可以出现在类中,成为一个字段(域);也可以出现在方法中,成为一个变量(还有一种是出现在方法参数中,但就其语义,和变量是类似的)。
如果int i是一个字段(域)定义,那么两者是没有任何区别的。因为,注意上面第二条带(*)的部分,当客户代码初始化当前类的对象时,会同时初始化这个i,将其值置为0。
如果int i是一个变量定义,那么,int i只是声明了一个局部变量,此时的i不能直接使用,必须首先赋值(如果未赋值就使用,会得到一个编译错误)。而int i = new int()则对i进行了一个初始化。
3 new约束
在泛型类型定义时,可以使用where指定一些约束,其中一种就是new约束。new 约束要求用作类型实参的类型必须带有公共无参构造器。如class A<T> where T : new();这里只有带有公共无参构造器的类型才能用作T。
需要注意两点,1)如果同时存在其他约束,那么new约束应该是最后一个。2)不能用new(int i)的形式来约束拥有指定签名的构造器。
好了,希望Anders Liu能给Anytao梳理一下文字。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述