请问NEW和USING的区别?

<转自>http://www.cnblogs.com/bytekiller/archive/2007/06/21/792411.html
请问NEW和USING的区别?
         很多公司的面试都可能问或是考查这个看似基础的东西,恕我浑浑噩噩,我可能回答的不够好!习惯性质的是由于我可能知道一些东西,但由于事务缠身,并没有去过多的关注部分细节,其间也没有得到某些无意或是有意的灌输,我可能会回答区别在于一个不会自动释放资源,一个会。那USING为甚么会了?在甚么时候使用USING合适?等
        我不知道在后面的回答是否都能把握的好,这只能说明我不够精通,但这些题目从来就没有给别人这样一个机会,假如你回答的不好,你是否能通过一种途径来找出区别,然后你再重新回答。
我笑了,假如我回答的不够好,我觉得后面是一个机会(也是一种能力的考察),我会通过甚么途径了,ILDASM,至少我知道我们生活再.NET的“蜜糖”中,我们有了好的高层次的框架,我有了很好的开发效率,但我忽视了细节,有很多时候,甚至懒得去关心细节,但这个题目让我觉得很丢脸,我回答的不好(阴沟里还翻了船) ,但我自知,秘密就藏再后面,于是我解开一段DEMO,看个明白。
using System;

namespace Demo
{
        
class Class1
    {
                [STAThread]
        
static void Main(string[] args)
        {
                        Test obj1
=new Test();


            
using(Test obj2=new Test())
            {
            }
        }
    }

    
class Test:System.IDisposable
    {
        
int a;
        
public int Val
        {
            
get
            {
                
return a;
            }
        }
        
#region IDisposable Members

        
public void Dispose()
        {
                    }

        
#endregion
    }
}
上面代码对应的IL语言解开了USING的秘密 (本人不才,到也研究过)
.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
  // Code size       25 (0x19)
  .maxstack  1                                            ---推导堆栈 
  .locals init ([0] class Demo.Test obj1,
           [1] class Demo.Test obj2)                --定义了两局部变量
  IL_0000:  newobj     instance void Demo.Test::.ctor()
  IL_0005:  stloc.0    -- 创建了Test对象并存放到 第一个局部量
  IL_0006:  newobj     instance void Demo.Test::.ctor()
  IL_000b:  stloc.1   -- 创建了Test对象并存放到第二个局部量
  .try
  {
    IL_000c:  leave.s    IL_0018  -- 你可以看作是GOTO语句 ,但是你要清楚,异常和RETURN,GOTO都不能逃出FINALLY,
  }  // end .try                                       FINALLY是一定会执行
  finally
  {
    IL_000e:  ldloc.1                        --载入局部量1,也是就我们用USING扩起的那个局部量)
    IL_000f:  brfalse.s  IL_0017        --发现,如果这个对象是NULL的,就结束  ,否则就调用对象上的DISPOSE方法(),哦原来如此
    IL_0011:  ldloc.1                      -- 我们终于发现了秘密,^_^,假如面试前你正好研究过,你回答的是否就更清晰!
    IL_0012:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_0017:  endfinally
  }  // end handler
  IL_0018:  ret
} // end of method Class1::Main
现在我要回答后面的问题了,是框架帮我做了手脚,他强制帮我调用对象的DISPOSE资源释放方法,而且,如果你的对象没有实现此IDISPOSABLE接口,却用了USING,编译是不会通过的哟!这里看来,USING的时机是当对象使用了非托管资源或是比较宝贵的资源,
而对于托管的或非宝贵的资源,我可以依赖GC,没有必要自己画蛇添足。而且TRY块是会影响效率的。

            请问FOREACH的机制是甚么?
哎!我就是用着爽嘛! 而且我几乎就把它当一个语法来看,谁又会没有刻意的却去看它的细节了,如果有的东东不清楚,我可以翻MSDN,我去GOOGLE搜,我自己看ILDASM,^_^,面试的人也不要因人家回答的不好就痞的人家一钱不值的样子(有这样的人,自命不凡而已)你非框架
的缔造者,微软的秘密多的去了,一个人是否能面面具到了,你是否就真的考察了能力,或只是换了皮囊的应试。希望这里也仍给人一个机会
找出这个机制,想想,我们访问一个ArrayList时,我用过,于是第二个DEMO出来
using System;
using System.Collections;

namespace Demo
{
    
    
class Class1
    {
        
        [STAThread]
        
static void Main(string[] args)
        {
            ArrayList arr
=new ArrayList();
            
foreach(object obj in arr)
            {
            }
        }
    }

    
}


.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
  // Code size       50 (0x32)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.Collections.ArrayList arr, --我们的列表对象
           [1] object obj,   --FOREACH中用到临时量
           [2] class [mscorlib]System.Collections.IEnumerator CS$00000006$00000000, --枚举器对象临时变量
           [3] class [mscorlib]System.IDisposable CS$00000002$00000001)   --这里我们看到定义了四个局部量

  IL_0000:  newobj     instance void [mscorlib]System.Collections.ArrayList::.ctor()  --我构造了列表对象。
  IL_0005:  stloc.0    -- 存起
  IL_0006:  ldloc.0    -- 推入推导堆栈
  IL_0007:  callvirt   instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.ArrayList::GetEnumerator()
  IL_000c:  stloc.2     // --我调用了GETENUMERATOR方法,它的作用是获得一个枚举器,这是你看到前面定义局部量还奇怪了
  .try   --进入TRY
  {
    IL_000d:  br.s       IL_0016    --无条件GOTO到IL_0016
    IL_000f:  ldloc.2   --MOVENET为真就会跳到这里来,这里仍需要枚举器对象,然后调用枚举器对象的GET_CURRENT方法获得遍历的对象
    IL_0010:  callvirt   instance object [mscorlib]System.Collections.IEnumerator::get_Current()
    IL_0015:  stloc.1    --将遍历的大的对象存到OBJ1中

    IL_0016:  ldloc.2  -- 载入变量2,变量2是个甚么东东,就是 TRY前的一句,得到的枚举器对象
    IL_0017:  callvirt   instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()   --调用这个枚举器对象的MOVENET方法。
    IL_001c:  brtrue.s   IL_000f    --如果MOVENET返回假,表明已经遍历到头了,真表示仍可以遍历,真跳到IL_000F
    IL_001e:  leave.s    IL_0031
  }  // end .try
  finally
  {
    IL_0020:  ldloc.2
    IL_0021:  isinst     [mscorlib]System.IDisposable    --看枚举器是否是一个IDISPOSABLE对象 就是 ENUMERATOR IS  IDISPOSABLE
    IL_0026:  stloc.3
    IL_0027:  ldloc.3
    IL_0028:  brfalse.s  IL_0030
    IL_002a:  ldloc.3
    IL_002b:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_0030:  endfinally
  }  // end handler
  IL_0031:  ret
} // end of method Class1::Main

      我们看到一些非我们定义的东西,甚么枚举器呀,GETEnumerator()来获得枚举器等等,于是会让我想看看ARRAYLIST的
实现,它究竟是耍了什么花招可以有这些了,你看看类库的反编译代码,你就发现,这些集合类实现了一个接口,那就是
System.Collections.IEnumerable (可枚举) ,这个接口也没搞甚么,就是要你实现一个System.Collections.IEnumerator接口的 对象,经MSDN翻查
我看到这个IEnumerator接口就定义甚么MOVENET, GET_CURRENT之类的,接口协定了行为的约束集合,是为了让框架能够服务于此,框架控制
了流程,它调用了我们的代码,对于我们来说,框架如何使用我们的代码是透明的,真的觉得框架类似一个功能强大的中间件哈!。
于是乎,我们明白了,我们知道了FOREACH的机制 是你实现IEnumerable,IEnumetrtor接口,能够让我们的一些对象能够遍历自己的部分的一种
能力,而FOREACH仅是个伪装的代码,它甚至就是一个高级的宏!就是一个宏的机制,但需要我们对某些对象实现一些特定的接口,否则这个
宏如何起作用了^_^。

      呵呵,清楚了吧,在我看到IL之前,或是我没有去关注过,我还真说不清楚FOREACH的机制(我只能搪塞),IDE是如何瞒天过海的做了那么多事情。

    说到最后,好比封箱拆箱,C#代码表面都是糊弄着我们,没人教你,你不看IL你能知道吗,我们决不要学人云亦云的人(知其所以然)
面试的过程不是简单的质检,你要给别人机会,那就是如果你不清楚,你会如何,或打算怎么去弄清楚,解决的途径,而
非一个绝对的答案。你应该学会接受这样的答案 (我对FOREACH不清楚,但是我会怎么样就可以怎么样去了解它。。。)
看别人对问题的态度和处理方式,在纸上写一个算法思路还可以,写个运行的程序,最是无趣了!
    注:本人水平有限,文中如有错误或不当之处 ,难免^_^

posted @ 2007-06-22 22:41  赖文华.NET  阅读(1339)  评论(0编辑  收藏  举报