小型网站网站建设需要,做书的封面网站,视频制作价格明细,桂林做网站多少钱[你必须知道的.NET] 第五回#xff1a;深入浅出关键字---把new说透 作者#xff1a;Anytao 本文将介绍以下内容#xff1a; 面向对象基本概念 new关键字深入浅出 对象创建的内存管理 1. 引言 园子里好像没有或者很少把new关键字拿出来说的#xff0c;那我就占个先机吧深入浅出关键字---把new说透 作者Anytao 本文将介绍以下内容 面向对象基本概念 new关键字深入浅出 对象创建的内存管理 1. 引言 园子里好像没有或者很少把new关键字拿出来说的那我就占个先机吧呵呵。那么我们到底有必要将一个关键字拿出来长篇大论吗看来是个问题。回答的关键是你真的理解了new吗如果是那请不要浪费时间如果不是那请继续本文的循序之旅。 下面几个 问题可以大概的考察你对new的掌握开篇之前希望大家做个检验如果通过了直接关掉本页即可。如果没有通过希望本文的阐述能帮你找出答案。 new一个class对象和new一个struct或者enum有什么不同 new在.NET中有几个用途除了创建对象实例还能做什么 new运算符可以重载吗 范型中new有什么作用 new一个继承下来的方法和override一个继承方法有何区别 int i和int i new int()有什么不同 2. 基本概念 一般说来new关键字在.NET中用于以下几个场合这是MSDN的典型解释 作为运算符 用于创建对象和调用构造函数。 本文的重点内容本文在下一节来重点考虑。 作为修饰符用于向基类成员隐藏继承成员。 作为修饰符基本的规则可以总结为实现派生类中隐藏方法则基类方法必须定义为virtualnew作为修饰符实现隐藏基类成员时不可和override共存原因是这两者语义相斥new用于实现创建一个新成员同时隐藏基类的同名成员而override用于实现对基类成员的扩展。 另外如果在子类中隐藏了基类的数据成员那么对基类原数据成员的访问可以通过base修饰符来完成。 例如 new作为修饰符using System;namespace Anytao.net.My_Must_net{ class Number { public static int i 123; public void ShowInfo() { Console.WriteLine(base class---); } public virtual void ShowNumber() { Console.WriteLine(i.ToString()); } } class IntNumber : Number { new public static int i 456; public new virtual void ShowInfo() { Console.WriteLine(Derived class---); } public override void ShowNumber() { Console.WriteLine(Base number is {0}, Number.i.ToString()); Console.WriteLine(New number is {0}, i.ToString()); } } class Tester { public static void Main(string[] args) { Number num new Number(); num.ShowNumber(); IntNumber intNum new IntNumber(); intNum.ShowNumber(); Number number new IntNumber(); //究竟调用了谁 number.ShowInfo(); //究竟调用了谁 number.ShowNumber(); } }} 作为约束用于在泛型声明中约束可能用作类型参数的参数的类型。 MSDN中的定义是new 约束指定泛型类声明中的任何类型参数都必须有公共的无参数构造函数。当泛型类创建类型的新实例时将此约束应用于类型参数。 注意new作为约束和其他约束共存时必须在最后指定。 其定义方式为 class GenericerT where T : new() { public T GetItem() { return new T(); } } 实现方式为 class MyCls { private string _name; public MyCls() { _name Emma; } } class MyGenericTester { public static void Main(string[] args) { GenericerMyCls MyGen new GenericerMyCls(); Console.WriteLine(MyGen.GetItem().Name); } } 使用new实现多态。 这不是我熟悉的话题详细的内容可以参见 《多态与 new [C#]》这里有较详细的论述。 3. 深入浅出 作为修饰符和约束的情况不是很难理解的话题正如我们看到本文开篇提出的问题也大多集中在new作为运算符的情况因此我们研究的重点就是揭开new作为运算符的前世今生。 Jeffrey Richter在其著作中极力推荐读者使用ILDASM工具查看IL语言细节从而提高对.NET的深入探究在我认为这真是一条不错的建议也给了自己很多提高的空间挖掘。因此以下是本人的一点建议我将在后续的系列中关于学习方法论的讨论中深入探讨这里只是顺便小议希望有益于大家。1 不断的学习代码2 经常看看IL语言的运行细节对于提供.NET的认识非常有效。 文归正题new运算符用于返回一个引用指向系统分配的托管堆的内存地址。因此在此我们以Reflector工具来了解以下new操作符执行的背后隐藏着什么玄机。 首先我们实现一段最简单的代码然后分析其元数据的实现细节来探求new在创建对象时到做了什么 new作为运算符using System;namespace Anytao.net.My_Must_net{ class MyClass { private int _id; public MyClass(int id) { _id id; } } struct MyStruct { private string _name; public MyStruct(string name) { _name name; } } class NewReflecting { public static void Main(string[] args) { int i; int j new int(); MyClass mClass new MyClass(123); MyStruct mStruct new MyStruct(My Struct); } }} 使用Reflector工具反编译产生的IL代码如下为 IL元数据分析.method public hidebysig static void Main(string[] args) cil managed{ .entrypoint .maxstack 2 .locals init ( [0] int32 num, [1] int32 num2, [2] class Anytao.net.My_Must_net._05_new.MyClass class2, [3] valuetype Anytao.net.My_Must_net._05_new.MyStruct struct2) L_0000: nop //初始化j为0 L_0001: ldc.i4.0 L_0002: stloc.1 //使用newobj指令创建新的对象并调用构造函数以0x76123的16进制初始化 L_0003: ldc.i4.s 0x7b L_0005: newobj instance void Anytao.net.My_Must_net._05_new.MyClass::.ctor(int32) L_000a: stloc.2 //加载“My Struct” L_000b: ldloca.s struct2 L_000d: ldstr My Struct //调用构造函数执行初始化 L_0012: call instance void Anytao.net.My_Must_net._05_new.MyStruct::.ctor(string) L_0017: nop L_0018: ret } 从而可以得出以下结论 new一个class时new完成了以下两个方面的内容一是调用newobj命令来为实例在托管堆中分配内存二是调用构造函数来实现对象初始化。 new一个struct时new运算符用于调用其带构造函数完成实例的初始化。 new一个int时new运算符用于初始化其值为0。 另外必须清楚值类型和引用类型在分配内存时是不同的值类型分配于线程的堆栈stack上并变量本身就保存其实值因此也不受GC的控制而引用类型变量包含了指向托管堆的引用内存分配于托管堆managed heap上内存收集由GC完成。 另外还有以下规则要多加注意 new运算符不可重载。 new分配内存失败将引发OutOfMemoryException异常。 对于基本类型来说使用new操作符来进行初始化的好处是某些构造函数可以完成更优越的初始化操作而避免了不高明的选择例如 string str new string(*, 100);string str new string(new char[] {a, b, c}); 而不是 string str ***************************************; 4. 结论 我能说的就这么多了至于透了没透作者的能量也就这么多了。希望园子的大牛们常来扔块砖头对我也是一种莫大的促进。但是作为基本的原理和应用我想对大部分的需求是满足了。希望这种力求深入浅出的介绍能给你分享new关键字和其本质的来龙去脉能有所帮助。 言归正传开篇的几个题目不知读者是否有了各自的答案我们不妨畅所欲言做更深入的讨论以便揭开其真实的面纱。 参考文献 USAStanley B.Lippman, C# Primer USADavid Chappell Understanding .NET 广而告之 [预告] 另外鉴于前几个主题的讨论中不管是类型、关键字等都涉及到引用类型和值类型的话题我将于近期发表相关内容的探讨同时还有其他的关键字值得研究这是本系列近期动向给自己做个广告。祝各位愉快。 [声明] 本文的关键字new指的是C#中的关键字概念并非一般意义上的.NET CRL范畴之所以将这个主题加入本系列是基于在.NET体系下开发的我们何言能逃得过基本语言的只是要点。所以大可不必追究什么是.NET什么是C#的话题希望大家理清概念有的放肆。