前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

C# new

作者头像
JusterZhu
发布2023-10-17 15:18:49
1340
发布2023-10-17 15:18:49
举报
文章被收录于专栏:JusterZhu

在C#中,new关键字有三种主要用法:

  1. new 运算符 (New Operator): 用于创建对象和调用构造函数。这是new关键字最常见的用法,用于实例化类和调用构造函数。
  2. new 修饰符 (New Modifier): 作为修饰符时,new关键字用于在派生类中隐藏从基类继承的成员,这样新的实现将会隐藏基类中的同名方法或属性。
  3. new 约束 (New Constraint): 用于在泛型声明中,指定泛型类型参数必须具有公共的无参数构造函数。这种用法确保了在泛型类型参数被实例化时,会调用该类型的默认构造函数。

new关键字在创建对象时做了哪些事情?

  1. 分配内存空间: new关键字会在堆内存中分配足够的内存空间来存储对象的数据。
  2. 调用构造函数: 构造函数是用于初始化对象的特殊方法。当使用new关键字创建对象时,相应类的构造函数会被调用,以便对对象进行初始化。如果类没有定义构造函数,系统会提供一个默认的构造函数。
  3. 初始化对象数据: 构造函数的代码会执行,用于设置对象的初始状态,包括成员变量的默认值等。
  4. 返回对象引用: new关键字会返回一个指向新创建对象的引用,允许在后续的代码中操作和访问该对象。

这些步骤确保了在创建对象时,对象的内存空间被正确分配,构造函数被调用以初始化对象,然后返回一个可以操作的对象引用。

new关键字在派生类中隐藏从基类继承的成员,这个隐藏怎么理解?

new关键字被用来显式隐藏从基类继承的成员。当派生类中的成员(方法、属性等)与基类中的成员同名时,通过使用new关键字,派生类可以隐藏基类的同名成员,即使它们的签名相同。这种隐藏并不影响基类中的成员,但在派生类的范围内,派生类的成员会覆盖基类的同名成员,从而隐藏它。使用new关键字可以让编译器知道你是故意隐藏了基类的成员。

例如,在基类中有一个名为Print的方法,在派生类中也定义了一个同名的Print方法,通过使用new关键字,派生类的Print方法将会隐藏基类的Print方法。但需要注意的是,这种隐藏是静态的,也就是说,在编译时就确定了使用哪个版本的方法,而不是在运行时动态决定。

new 泛型约束,是怎么实现约束的?

这里参考和搬运沉睡的木木夕的文章:https://www.cnblogs.com/ms27946/p/Note-About-The-Generic-Constraint-Of-New.html

先来看一段泛型约束的示例代码:

代码语言:javascript
复制
public static T CreateInstance<T>() where T: new() => new T();

如果说我们不知道泛型底下到底做了什么操作,我们也不用急,我们可以用 ILSpy 来看查看一下,代码片段如下:

代码语言:javascript
复制
.method public hidebysig static 
    !!T CreateInstance<.ctor T> () cil managed 
{
    // Method begins at RVA 0x2053
    // Code size 6 (0x6)
    .maxstack 8
    
    IL_0000: call !!0 [System.Private.CoreLib]System.Activator::CreateInstance<!!T>()
    IL_0005: ret
} // end of method C::CreateInstance

在 IL_0000 就能明显看出泛型约束 new() 的底层实现是通过反射来实现的。至于 System.Activator.CreateInstance<T> 方法实现我在这里就不提了。只知道这里用的是它就足够了。不知道大家看到这里有没有觉得一丝惊讶,我当时是有被惊到的,因为我的第一想法就是觉得这么简单肯定是直接调用无参 .ctor,居然是用到的反射。毕竟编译器拥有在编译器就能识别具体的泛型类了。现在可以马后炮的讲:正因为是编译器只有在编译期才确定具体泛型类型,所以编译器无法事先知道要直接调用哪些无参构造函数类,所以才用到了反射。

关于 System.Activator.CreateInstance<T>() 的方法描述,在微软官网api中的remark部分有提到。

如果本文仅仅只是这样,那我肯定没有勇气写下这片文章的。因为其实已经有人早在 04 年园子里就提到了这一点。但是我查到的资料也就止步于此。

试想一下 ,如果你的框架中有些方法用到了无参构造函数泛型约束,并且处于调用的热路径上,其实这样性能是大打折扣的,因为反射 Activator.CreateInstance 性能肯定是远远不如直接调用无参构造函数的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JusterZhu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • new关键字在创建对象时做了哪些事情?
  • new关键字在派生类中隐藏从基类继承的成员,这个隐藏怎么理解?
  • new 泛型约束,是怎么实现约束的?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档