C#中的new

根据MSDN上的介绍:https://msdn.microsoft.com/zh-cn/library/fa0ab757.aspx


1.用于创建对象和调用构造函数。 例如:Class1 obj  = new Class1();  

2.还可用于创建匿名类型的实例:

var query = from cust in customers  

select new {Name = cust.Name, Address = cust.PrimaryAddress}; 

3.new 运算符还用于调用值类型的默认构造函数。 例如:int i = new int();  

在上一个语句中,i 初始化为 0,它是 int 类型的默认值。 该语句的效果等同于:int i = 0;  

4.有关默认值的完整列表,请参见默认值表。
请记住,为结构声明默认的构造函数是错误的,因为每一个值类型都隐式具有一个公共的默认构造函数。 可以在结构类型上声明参数化构造函数以设置其初始值,但是,只有在需要默认值之外的值时才必须这样做。
值类型对象(例如结构)是在堆栈上创建的,而引用类型对象(例如类)是在堆上创建的。 两种类型的对象都是自动销毁的,但是,基于值类型的对象是在超出范围时销毁,而基于引用类型的对象则是在对该对象的最后一个引用被移除之后在某个不确定的时间销毁。 对于占用固定资源(例如大量内存、文件句柄或网络连接)的引用类型,有时需要使用确定性终止以确保对象被尽快销毁。 
不能重载 new 运算符。如果 new 运算符分配内存失败,将引发异常 OutOfMemoryException。


关于上述第三点,我在另外一篇文章" C#性能优化5大技巧(最高可达62倍)"中看到作者说new 运算符用于调用值类型的默认构造函数会影响性能。

我用该文中的程序并改不同的值去试了下,截图如下:

  

从测试结果看,当一次性new很多个int的时候,性能上确实会有所影响。


但我从IL代码上看,发现(1)int a=new int();(2)int a;a=0;的IL代码完全一样。

所以上述造成性能差异的原因应该是在该程序中的方式(1)中多了一条赋值语句导致的。大家可以看看下面这篇文章~






下面是该文原文和链接:http://blog.csdn.net/z2516305651/article/details/52353450?locationNum=15&fps=1

1、你是否用异常机制来处理过用户输入验证?

如果是,那么你的程序性能已经降低了62倍。你不相信吗?等几分钟,我将会告诉你怎么回事。但是在示例之前,我们先了解清楚哪里进行异常是真正必要的。

举个例子,你验证用户输入的数据,如果无效,则抛出异常到客户端(我假定你是基于业务逻辑校验用户输入的)。

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. class BusinessLogcCheck  
  2. {  
  3.     public void Check()  
  4.     {  
  5.         try  
  6.         {  
  7.             //Your validation code is here  
  8.              
  9.         }  
  10.         catch (Exception ex)  
  11.         {  
  12.             throw new Exception("My own exception");  
  13.         }  
  14.    
  15.     }  
  16. }  

亲爱的朋友,在接下来的例子中,当你看到了屏幕输出的结果后,你将会认识到那是多么糟糕的习惯。让我们来看下面的代码。

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Diagnostics;  
  6. using System.IO;  
  7. using System.Net;  
  8. using System.Net.NetworkInformation;  
  9. namespace Test1  
  10. {  
  11.     class Program  
  12.     {  
  13.         public static void ThrowTest()  
  14.         {  
  15.             throw new Exception("This is exceptopn");  
  16.         }  
  17.         public static Boolean Return()  
  18.         {  
  19.             return false;  
  20.         }  
  21.    
  22.         static void Main(string[] args)  
  23.         {  
  24.    
  25.             Stopwatch sw = new Stopwatch();  
  26.             sw.Start();  
  27.    
  28.             try  
  29.             {  
  30.                     ThrowTest();  
  31.             }  
  32.             catch  
  33.             {  
  34.                  
  35.             }  
  36.             sw.Stop();  
  37.             Console.WriteLine("With Exception " + sw.ElapsedTicks);  
  38.    
  39.             sw.Restart();  
  40.             try  
  41.             {  
  42.                 Return();  
  43.             }  
  44.             catch  
  45.             {  
  46.    
  47.             }  
  48.             sw.Stop();  
  49.             Console.WriteLine("With Return " + sw.ElapsedTicks);  
  50.             Console.ReadLine();  
  51.         }  
  52.     }  
  53. }  

这是你正在等待的输入结果。

Image1.jpg


我的证明非常简单。在一个函数中引发一个异常,而在另一个函数中返回用户输入校验后的布尔值。而且我附加了一个计算器让你相信异常处理是如何影响代码性能的。

所以我们可以得出一个结果:不要针对用户输入验证抛出一个异常,而使用布尔值来返回验证输入的业务逻辑(或者其他相似的技术)。因为异常对象代价太高了。(不过也高不过你所钟爱的衬衣。哈哈)

2.绝对不要在循环中使用try-Catch.

是的,这也是和异常处理相关的。我再重复一遍:绝对不要在循环中使用try-Catch。让我用一个例子来证明。

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Diagnostics;  
  6. using System.IO;  
  7. using System.Net;  
  8. using System.Net.NetworkInformation;  
  9. namespace Test1  
  10. {  
  11.     class Program  
  12.     {  
  13.         static void Method1()  
  14.         {  
  15.             for (int i = 0; i < 1000; i++)  
  16.             {  
  17.                 try  
  18.                 {  
  19.                     int value = i * 100;  
  20.                     if (value == -1)  
  21.                     {  
  22.                         throw new Exception();  
  23.                     }  
  24.                 }  
  25.                 catch  
  26.                 {  
  27.                 }  
  28.             }  
  29.         }  
  30.         static void Method2()  
  31.         {  
  32.             try  
  33.             {  
  34.                 for (int i = 0; i < 1000; i++)  
  35.                 {  
  36.                     int value = i * 100;  
  37.                     if (value == -1)  
  38.                     {  
  39.                         throw new Exception();  
  40.                     }  
  41.                 }  
  42.             }  
  43.             catch  
  44.             {  
  45.             }  
  46.         }  
  47.    
  48.         static void Main(string[] args)  
  49.         {  
  50.    
  51.             Stopwatch sw = new Stopwatch();  
  52.             sw.Start();  
  53.             Method1();  
  54.             sw.Stop();  
  55.    
  56.             Console.WriteLine("Within Loop " + sw.ElapsedTicks);  
  57.    
  58.             sw.Restart();  
  59.             Method2();  
  60.             sw.Stop();  
  61.             Console.WriteLine("Outside of Loop " + sw.ElapsedTicks);  
  62.             Console.ReadLine();  
  63.         }  
  64.     }  
  65. }  
这是屏幕输出结果。

Image2.jpg

在这个程序中,方法1我在for循环中实现了异常处理机制,在方法2中则没有。输出结果说明在循环外面比在循环里面处理异常会快上2倍。

于是我们又得到一个结论:在项目中,不要在循环内部实现try-catch。(注意:不只是for循环,包括所有的循环。)


3.你是否疯狂了,以致于使用new操作符来创建整型变量?

亲爱的读者,不要为标题太长而怪我。绝不要使用new操作符来创建一个简单的整型变量。我知道你将会争辩说,如果你使用new操作符去创建一个简单的整型变量,系统会自动赋值为0,这样就可以免除像“变量未赋值”的错误。但是,在你创建本地变量去储存的位置,真的有必要自动赋值为0吗?让我们看看new操作符是如何把代码执行性能拖慢的。

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Diagnostics;  
  6. using System.IO;  
  7. using System.Net;  
  8. using System.Net.NetworkInformation;  
  9. namespace Test1  
  10. {  
  11.     class Program  
  12.     {  
  13.         static void Main(string[] args)  
  14.         {  
  15.             Stopwatch sw = new Stopwatch();  
  16.             sw.Start();  
  17.             for (int i = 0; i < 1000; i++)  
  18.             {  
  19.                 int a = new int();  
  20.                 a = 100;  
  21.             }  
  22.             sw.Stop();  
  23.             Console.WriteLine("Using New operator:- " + sw.ElapsedTicks);  
  24.             sw.Restart();  
  25.             for (int i = 0; i < 1000; i++)  
  26.             {  
  27.                 int a;  
  28.                 a = 100;  
  29.             }  
  30.             sw.Stop();  
  31.             Console.WriteLine("Without new operator:- "+ sw.ElapsedTicks);  
  32.             Console.ReadLine();  
  33.         }  
  34.     }  
  35. }  

这是输出快照。

Image3.jpg

是的,new操作符将执行速度拖慢了5倍。嗯...Sourav,我可以举出一个问题来否认结果。你一次创建1000个变量,而在我们的项目中是不可能一次创建1000个变量的。我们最多也只是创建2个或者3个。

OK!如果你的程序是web程序呢?如果你要校验流行的web程序的点击数,我确定每天将会超过1000个。

因此,我们又得到了一个结论:别太疯狂的使用new操作符来创建整型变量。


4.根据目的选择最好的集合。

作为.NET开发者,对于C#中的集合是非常熟悉的,而且他们到处被用于存值。让我们看看查询整数的性能如何?这是我的代码。

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Diagnostics;  
  6. using System.IO;  
  7. using System.Net;  
  8. using System.Net.NetworkInformation;  
  9. namespace Test1  
  10. {  
  11.     class Program  
  12.     {  
  13.         static void Main(string[] args)  
  14.         {  
  15.             List<Int32> li = new List<Int32>(1000);  
  16.             Dictionary<intint> di = new Dictionary<intint>(1000);  
  17.             int[] arr = new int[1000];  
  18.             int a;  
  19.              
  20.             for (int i = 0; i < 1000; i++)  
  21.             {  
  22.                 li.Add(i);  
  23.                 di.Add(i, i);  
  24.                 arr[i] = i;  
  25.             }  
  26.    
  27.             Stopwatch sw = new Stopwatch();  
  28.             sw.Start();  
  29.             a = li[500];  
  30.             sw.Stop();  
  31.             Console.WriteLine("From list:- " + sw.ElapsedTicks);  
  32.    
  33.    
  34.             sw.Start();  
  35.             a = arr[500];  
  36.             sw.Stop();  
  37.             Console.WriteLine("From Integer array:- " + sw.ElapsedTicks);  
  38.    
  39.    
  40.             sw.Restart();  
  41.             a = di[500];  
  42.             sw.Stop();  
  43.             Console.WriteLine("From Dictionary:- " + sw.ElapsedTicks);  
  44.             Console.ReadLine();  
  45.         }  
  46.     }  
  47. }  
这是输出结果。

Image4.jpg

我们可以清晰的看到,字典集合的查询性能是最差的,而表单和整型数据的性能差不多。

Image5.jpg


5.函数很好,但有时却不时。

如果你们还记得学习编程的日子,你们学到的第一个概念一般都是函数实现是一个好习惯,而且也很乐于将函数实现作为一个主要任务。函数在编程中有成千上万的优点,但是我们还是要看看函数是如何降低执行性能的。不过,这样的目的并不是反对函数,而是向你展示函数调用是有代价的机制,并且提供了一个观点:哪里需要实现函数,哪里不需要实现函数。让我们看看下面的代码。

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Diagnostics;  
  6. using System.IO;  
  7. using System.Net;  
  8. using System.Net.NetworkInformation;  
  9. namespace Test1  
  10. {  
  11.     class test  
  12.     {  
  13.         public static void Print()  
  14.         {  
  15.             Console.WriteLine("I am function from Class");  
  16.         }  
  17.     }  
  18.    
  19.    
  20.     class Program  
  21.     {  
  22.         static void Main(string[] args)  
  23.         {  
  24.             Stopwatch sw = new Stopwatch();  
  25.             sw.Start();  
  26.             test.Print();  
  27.             sw.Stop();  
  28.             Console.WriteLine(sw.ElapsedTicks);  
  29.    
  30.             sw.Restart();  
  31.             Console.WriteLine("I am single statement within main");  
  32.             sw.Stop();  
  33.             Console.WriteLine(sw.ElapsedTicks);  
  34.    
  35.             Console.ReadLine();  
  36.         }  
  37.     }  
  38. }  

这是输入结果。

Image6.jpg

这里我想在窗口上打印简单的信息,第一次调用类的静态方法,第二次直接在主函数中输出。是非常简单的Console.Writeline().而从屏幕输出的结果说明简单的单行输出比函数快了9倍。很显然,我们并没有去争论“函数的优缺点”的问题。(哈哈)

所以,我们又得到了一个简单的结论:在盲目实现一个函数前,先尝试理解情景,再作出最好的决定。


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值