基础回顾-using指令在命名空间(namespace)外部或内部会影响程序集的加载吗?

C#开发 2015-09-16 2155浏览 收藏本文

命名空间(namespace),using指令这是我们在初学C#开发时就认识并掌握了的基础知识。今天我在逛Scott Hanselman的个人网站时又看到一篇关于C#命名空间和using指令相关的文章,翻译过来为《回归基础-命名空间using指令会影响程序集的加载吗?》,正好自己也再复习一下这方面的基础知识。 好,下面我们切入正题,通过代码示例和分析来重新梳理。 如下面示例中的using方式(using指令在namespace的外部)代码,是可以正常的编译的:

/*
回归基础-命名空间using指令会影响程序集的加载吗?
*/
using Guid = System.Guid;
namespace NamespaceDemo
{
  public class Program
  {
    static void Main(string[] args)
    {
      Guid g = new Guid("Hello world.");
    }
  }
  public class Guid
  {
    public Guid(string s) { }
  }
}
但是,如下面代码所示,我们把using指令移到命名空间(namespace NamespaceDemo)的内部,编辑器就感知到了错误,提示:“命名空间NamespaceDemo包含与别名‘Guid’冲突的定义”。
/*
回归基础-命名空间using指令会影响程序集的加载吗?
*/
namespace NamespaceDemo
{
  using Guid = System.Guid;
  public class Program
  {
    static void Main(string[] args)
    {
      Guid g = new Guid("Hello world.");
    }
  }
  public class Guid
  {
    public Guid(string s) { }
  }
}
编辑器错误感知如图: namespace-sample-01 在第一个示例中,我们创建了一个名为“Guid”别名的using指令,但这不会影响,因为Guid类在NamespaceDemo的内部,我们在使用Guid时,编译器识别的是内部的Guid类,所以没有冲突。 在第二个示例中,我们把using指令移到中了NamespaceDemo的命名空间内部,出现了两个相同命名的Guid的声明,这时产生了命名冲突导致编译器不能自动决定如何编译。这样的冲突只会在第二个示例的情形中出现,也就是using指令在命名空间(namespace)的内部。
有人认为“把using指令放在命名空间的内部时允许框架在运行时懒加载所引用的程序集。也就是说,如果引用中的代码没有被执行,那么可以完全避免加载没有被用到的引用程序集。”
但作者Scott Hanselman并不这样认为的。他认为:一个using指令只是一个别名或者说是一种语法糖。最终的IL是相同的。程序集加载不会受到程序集的装载而改变。 以下是一些测试,测试用例一
using System;
using System.Xml;
 
namespace Microsoft.Sample
{
   public class Program
   {
      public static void Main(string[] args)
      {
         Guid g = Guid.NewGuid();
         Console.WriteLine("Before XML usage");
         Console.ReadLine();
         Foo();
         Console.WriteLine("After XML usage");
         Console.ReadLine();
      }
 
      public static void Foo()
      {
         XmlDocument x = new XmlDocument();
      }
   }
}
当程序在调试模式下运行后,屏幕会运行到ReadLine()这行,等待用户按键,这时,我们打开任务管理器查看进程,如图: namespace-sample-02 然后,我们按下Enter键,程序会运行Foo()方法,并创建一个XmlDocument的实例。这时,我们再查看进程,会看到System.Xml已经被加载了: namespace-sample-03 第二个测试,把using指令移到namespace内部:
namespace Microsoft.Sample
{
   using System;
   using System.Xml;
 
   public class Program
   {
      public static void Main(string[] args)
      {
         Guid g = Guid.NewGuid();
         Console.WriteLine("Before XML usage");
         Console.ReadLine();
         Foo();
         Console.WriteLine("After XML usage");
         Console.ReadLine();
      }
 
      public static void Foo()
      {
         XmlDocument x = new XmlDocument();
      }
   }
}
然后以同样的方式运行以上程序,结果和第一个测试是一样的。 如果切换到Release模式下再运行程序,程序会被立即加载。所以到目前的测试为止,我们可以得出手结论是:不管是把using指令写在namespace外部还是namespace的内部,都不会影响到程序集的加载。  

转载请注明:图享网 » 基础回顾-using指令在命名空间(namespace)外部或内部会影响程序集的加载吗?