一、new的基本功能

一般说来,new关键字在.net中用于以下四个场合。

  1. 作为运算符,用于创建对象和调用构造函数,范围用得最多吧。
  2. 实现多态。
  3. 作为修饰符,用于向基类成员隐藏继承类成员,一般继承情况下,扩展基类方法用得多。
  4. 作为泛型参数约束,用于在泛型声明中约束用作类型参数的参数类型,这个也好像用得多吧。

二、new的基本用法

  1. 先来说说作为泛型参数约束的用法。
MSDN 中的定义是:new约束指定泛型类声明中的任何类型参数都必须有公共的无参构造函数。当泛型类型创建类型的新实例时,将此约束应用于类型参数。
有个注意的地方就是有其他约束时,new约束比须最后指定。
下面实现一个例子:

1     class Person<T> where T : new()
2     {
3         public T GetName()
4         {
5             return new T();
6         }
7     }

9     class Boy
10     {
11         private string _name;
12 
13         public string Name
14         {
15             get{return _name;}
16             set { _name = value; }
17         }
18 
19         public Boy()
20         {
21             _name = "feng";
22         }
23     }
24 
25     class Program
26     {
27         static void Main(string[] args)
28         {
29             Person<Boy> MBoy = new Person<Boy>();
30 
31             Boy a = new Boy();
32             Console.WriteLine(a.Name);
33 
34             Console.WriteLine(MBoy.GetName().Name);
35             Console.ReadKey();
36         }
37     }   

结果 打印出2个"feng"

2.  再来说说作为修饰符和多态的用法。

作为修饰符,主要用在向基类成员隐藏继承成员。如果要实现派生类隐藏方法,则基类的方法必须定义为virtual,将基类方法实现为virtual可以保证向前扩展和向后兼容。分别在派生类通过override或new进行灵活控制。new和overdide不可同时共存,因为new用于创建一个新成员,同时隐藏基类的同名成员,注意不是覆盖,要想访问基类的成员可以通过base修饰符来访问。而override则不行。

通过new实现多态。

  1. 比如通过基类扩展来实现继承式多态:

    Animal a =new dog();

    //其中cry()方法实现为虚方法,子类dog继承至Animal 并覆写了该方法,虽然a是父类Animal的一个变量,但是实现的是子类dog的方法,这正是new实现多态的体现吧。

a.cry();

2.也可以通过继承接口来实现多态:

IAnimalRun r=new dog();//dog实现了接口IAnimalRun 的 run()方法

r.run();

看下面一个例子来加深理解:

1     class Num
 2     {
 3         public static int i = 111;
 4 
 5         public virtual void ShowClassInfo()
 6         {
 7             Console.WriteLine("我是基类呵呵");
 8         }
 9         public virtual void ShowNum()
10         {
11             Console.WriteLine("基类的数字是{0}", i.ToString());
12         }
13     }
14 
15     class SubNum : Num
16     {
17         new public static int i = 222;
18 
19         //new 作为修饰符:只是隐藏基类同名方法
20         public new virtual void ShowClassInfo()
21         {
22             Console.WriteLine("我是子类哈哈");
23         }
24 
25         //override则是覆写了基类的方法
26         public override void ShowNum()
27         {
28             Console.WriteLine("子类的数字是{0}", i.ToString());
29         }
30     }
31 
32     class Program
33     {
34         static void Main(string[] args)
35         {
36             Num num1 = new Num();//new 运算符用法
37             num1.ShowNum();
38             SubNum sbnum = new SubNum();
39             //下面2个调用的都是子类的方法 但是实现机制不一样
40             sbnum.ShowNum();//结果:111
41 
42             sbnum.ShowClassInfo();//结果:我是子类
43             
44             //new作为多态的用法:下面是典型的基类继承似多态
45             Num num2 = new SubNum();//num2虽然是基类的变量,但是指向了之类SubNum实例的引用
46 
47             //调用方法时会在运行期检查虚拟方法表,来确定要调用的方法
48             num2.ShowClassInfo();//由于方法只是被隐藏了,没有被重写 所有还是调用的基类的方法
49 
50             num2.ShowNum();//方法被覆盖了 所有调用的是子类的方法
51             Console.ReadKey();
52         }
53     }

个人觉得new实现多态可以放到作为运算符里面不去,不知道你们是不是这样认为的。

3.作为运算符的用法。

作为修饰符和约束的情况也许要多加理解,作为运算符一定是一个不难理解的话题,因为大多数时候我们就是用new作为运算符来创建对象或结构体或枚举等等。new运算符用于返回一个引用,指向系统分配的托管堆的内存地址,那new实例化值类型和引用类型有啥区别呢,来看一段简单的代码。

class MyClass
 2     {
 3         private int _id;
 4         public MyClass(int id)
 5         {
 6             _id = id;
 7         }
 8     }
 9 
10     struct MyStruct
11     {
12         private string _name;
13         public MyStruct(string name)
14         {
15             _name = name;
16         }
17     }
18 
19     class Program
20     {
21         public static void Main()
22         {
23             int i=0;
24             int j = new int();
25             string str = new string('#', 10);
26 
27             MyClass myClass = new MyClass(123);
28 
29             MyStruct myStruct = new MyStruct("hehe");
30             
31             Console.WriteLine(j);
32             Console.ReadKey();
33         }
34     }

我们来用reflector工具来查看它的IL代码如下:

.method public hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 3
    .locals init (
        [0] int32 num,//这里我创建的明明是i反编译确是num 不理解,求大家指出
        [1] int32 j,//这里我自己修改成了j
        [2] string str,
        [3] class TestNewFunction.MyClass myClass,
        [4] valuetype TestNewFunction.MyStruct myStruct)
    L_0000: nop 

//手动初始化i为0

L_0001: ldc.i4.0 
    L_0002: stloc.0

//通过new来初始化j为0

L_0003: ldc.i4.0 //j的值为0
    L_0004: stloc.1

//调用newobj初始化字符串str

L_0005: ldc.i4.s 0x23//'#'的16进制
    L_0007: ldc.i4.s 10//这个10应该是count
    L_0009: newobj instance void [mscorlib]System.String::.ctor(char, int32)

L_000e: stloc.2

//调用newobj创建对象,并调用构造函数初始化 ,内存分配在托管堆上

L_000f: ldc.i4.s 0x7b//111的十六进制
    L_0011: newobj instance void TestNewFunction.MyClass::.ctor(int32)
    L_0016: stloc.3

//加载结构体

L_0017: ldloca.s struct2
    L_0019: ldstr "hehe"

//调用构造函数初始化,内存分配在线程的栈上面

L_001e: call instance void TestNewFunction.MyStruct::.ctor(string)
    L_0023: nop 
    L_0024: ldloc.1 
    L_0025: call void [mscorlib]System.Console::WriteLine(int32)
    L_002a: nop 
    L_002b: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
    L_0030: pop 
    L_0031: ret 
}

本人对IL知道的不是很多,有错误希望大家能够提出来。通过以上分析,可以得出一点结论:

  1. new一个class时,先调用newobj命令 来为实例在托管堆中分配内存,然后调用构造函数来进行对象初始化。
  2. new 一个struct 时,直接调用其构造函数完成初始化。
  3. new 一个int时,用于初始化其值为0。

差点忘了 new运算符不可重载,分配内存失败时,会引发OutOfMemoryException异常。

以上是本人对new这个关键字的用法。如有错误欢迎指出。

原文出处:章出处:http://www.cnblogs.com/xingbinggong/archive/2011/07/05/2098454.html

转载于:https://www.cnblogs.com/Microscope/p/4204901.html

.Net 基础new关键字的用法相关推荐

  1. python中使用函数的优点_Python基础之函数基本用法与进阶详解

    本文实例讲述了Python基础之函数基本用法与进阶.分享给大家供大家参考,具体如下: 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数 ...

  2. python基础函数及用法意思_Python基础之函数基本用法与进阶详解

    本文实例讲述了Python基础之函数基本用法与进阶.分享给大家供大家参考,具体如下: 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数 ...

  3. JAVA多线程基础篇-关键字synchronized

    1.概述 syncronized是JAVA多线程开发中一个重要的知识点,涉及到多线程开发,多多少少都使用过.那么syncronized底层是如何实现的?为什么加了它就能实现资源串行访问?本文将基于上述 ...

  4. Python实用技巧:global关键字的用法详解

    这篇文章主要介绍了python global关键字的用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下: 想要更好的了解global关键字,首先 ...

  5. java关键字的用法_JAVA常用关键字及其用法简要说明

    JA V A常用关键字及其用法简要说明Abstract抽象的一个Java语言中的关键字,用在类的声明中来指明一个类是不能被实例化的,但是可以被其它类继承.一个抽象类可以使用抽象方法,抽象方法不需要实现 ...

  6. 【转载】register、volatile、restrict 三关键字的用法

    原文地址:register.volatile.restrict 三关键字的用法 – RaymondAmos的技术专栏 – CSDN博客. register 使用修饰符register声明的变量属于寄存 ...

  7. java编程里的values怎么使用,详解Java编程中super关键字的用法

    这篇文章主要介绍了Java编程中this与super关键字的用法,包括从内存结构方面分析super的作用域,需要的朋友可以参考下 通过用static来定义方法或成员,为我们编程提供了某种便利,从某种程 ...

  8. escape mysql_MySQL中ESCAPE关键字的用法详解

    MySQL转义 转义即表示转义字符原来的语义,一个转义字符的目的是开始一个字符序列,使得转义字符开头的该字符序列具有不同于该字符序列单独出现时的语义. MySQL中,转义字符以"" ...

  9. __declspec关键字详细用法

    __declspec关键字详细用法 2009-01-21 16:23 __declspec用于指定所给定类型的实例的与Microsoft相关的存储方式.其它的有关存储方式的修饰符如static与ext ...

最新文章

  1. PagingAndSortingRepository接口与 JpaRepository接口
  2. python代码案例详解-Python实现电视里的5毛特效实例代码详解
  3. Razor @Html.Raw()的作用
  4. 如何生成文件夹目录树文件
  5. linux命令history
  6. 盘式制动系统卡钳分类
  7. 基于python3写的源码剖析_Python 极简插件系统 pluggy 源码剖析
  8. z-index ie无效
  9. JavaScript实现继承的方式,不正确的是:
  10. android 复制u盘文件到手机本地_如何导出Android中的文件(把Android当做U盘)
  11. css hack 记录
  12. vasp软件linux,QVASP 是一款 VASP 的辅助软件
  13. MySQL之InnoDB存储引擎
  14. CSS Hack(兼容ie8一下的浏览器)
  15. 京委本圣经的历史考证
  16. 数据链路层 - MTU 、ARP协议
  17. 银行mysql面试题_mysql的常见面试题
  18. linux here,here交友app-here官网版下载v1.0-Linux公社
  19. 周报,当前是第几周 ?
  20. 低调,中国的FPGA到底有多强?

热门文章

  1. oralce mysql_Oralce和Mysql的3个区别
  2. 网络推广平台浅析通常网站关键词优化密度该如何把控呢?
  3. 免费网络推广浅析对网站首页优化的注意细节把控!
  4. 企业网络推广方法之网站内容链接SEO该怎么做?
  5. 网站URL怎样优化才比较合理?
  6. 裸奔浏览器_大概是最好用的隐私浏览器 - Firefox Focus
  7. java 值类型与引用类型_JAVA 关于值类型和引用类型的区别
  8. linux cache lru回收,LRU cache 算法
  9. 微信小程序从oracle取数,微信小程序 取随机数
  10. 英特尔nuc能代替主机吗_制砂机生产的沙子可靠吗?能代替天然沙子吗?