`
cdragon
  • 浏览: 76992 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

effective hierarchy(一)之 基本概念(4)

阅读更多

MSDN,C#2.0:

 

一、名字空间和类型名称(namespace and type names)

 

 1.在C#程序中,有几个(serveral)语境上下文(context)是要求必须指定“名字空间或类型的名称”(namespace-or-type-name以下简为ntn)的。它们都写成以“.”记号分隔的一个或多个标识符(identifier)。语法格式为:

    namespace-name:  

    type-name:

         qualified-alias-member

 

    namespace-or-type-name:

         namespace-or-type-name . identifier type-argument-listopt 

 

 2.意义

     一个类型名(type-name)是引用(refer to)一个类型(type)的ntn。遵循以下规则:某类型名的ntn必须引用某类型。否则,发生编译时错误(compile-time error);

   一个名字空间名(namespace-name)是引用一个名字空间的ntn。遵循以下规则:某名字空间名的ntn必须引用某名字空间。否则,发生编译时错误。(另,type-argument不能出现在名字空间名中。)

 

 3.不属于限定别名成员的ntn,有四种形式:

  • I
  • I<A1, ..., AK>
  • N.I
  • N.I<A1, ..., AK>

    这里I是单修饰符,N是一个ntn,<A1, ..., AK>是可选的类型参数列表,当没有指明类型参数列表时,视K=0。

 

 4.ntn的含义(meaning),即解析,用以下方式确定:

 

   (1)ntn由单个标识符组成:

 

    a.ntn出现在类或结构声明体内,则从该类或结构的声明开始(查找)--又,如果存在封闭(enclosing)它的类或结构,则遍及(continuing with)之--如果具有给定名称(given name)的成员是存在的、可访问的,且表示(denote)某类型(type),那么ntn指向(refer to)这个成员。注意,当确定某ntn的含义时,会忽略非类型成员,如常量、字段、方法、属性、索引器、运算符、实例构建器、析构器、静态构建器。否则,

 

      b.从发生ntn的名字空间开始(starting with)--又,如果封闭它的名字空间存在,则遍及之--以全局名字空间(global namespace)结束。期间测算(evaluate)下列步骤直至定位到某实体(entity):

 

       1'.如果名字空间包含具有给定名称的名字空间成员,则ntn指向该成员,并以其(该成员)为依据,将ntn归属(classified)到(一个)名字空间或(一个)类型。否则,

 

       2'.如果名字空间具有--与包含(enclosing)ntn发生位置--对应的名字空间的声明,那么,

 

      ~如果名字空间声明包含一个using别名指令(using-alias-directive)--该指令将给定的名称和导入(imported)的名字空间或类型相关联,那么ntn引用该名字空间或类型。否则,

 

          ~如果用using名字空间指令(using-namespace-directives)导入的名字空间,在它的名字空间定义(namespace declaration )中,包含和给定的名称完全匹配的一个类型,那么ntn引用该类型。否则,

 

          ~如果用using名字空间指令导入的名字空间,它的名字空间定义包含多个具有给定名称的类型,那么ntn含义不清(ambiguous)而发生错误(error);否则,

 

          ~ntn是未定义的,发生编译时错误。

 

 

   (2)否则,如果ntn是N.I的形式,其中:N包括除最右边(那个)标识符以外的全部标识符(identifier),I则是最右边的那个标识符。N首先作为ntn解析(resolved as),如果该解析不成功,发生编译时错误。否则:

 

      1'如果N是一个名字空间,I是该名字空间可访问的成员名字,则N.I指向该成员,且据该成员,归属到一个名字空间或类型;

 

      2'如果N是一个类或结构类型,并且I是N中可访问类型的名字,则N.I指向该类型。否则,

 

      3'N.I作为无效的ntn,发生编译时错误。

 

    从以上可以看出,无论是单修饰符,还是采N.I形式,NTN最终用来确定它是namespace还是type类别. 

 

 5.完全限定名称(fully qualified names)

 

  (1)每个名字空间或类型都有一个完全限定名,它唯一地标识出与其它的名字空间或类型的区别。一个名字空间或类型N是由以下情况确定:

 

      1'如果N是全局名字空间的成员,它的完全限定名就是N。否则,

      2'它的完全限定名是S.N,其中S是“名字空间或类型”(N声明于其中)的完全限定名;

 

  (2)换句话说,N的完全限定名是从全局名字空间开始一直到(lead to)N的标识符的“全层次”的路径。因为名字空间或类型的每个成员都必须有一个唯一名称--它遵循(一个)名字空间或类型完全限定名总是唯一的原则。

         

//下面的示例是几个名字空间和类型,右侧的注释是它的完全限定名
class A {}            // A

namespace X            // X
{
   class B            // X.B
   {
      class C {}      // X.B.C
   }
   namespace Y         // X.Y
   {
      class D {}      // X.Y.D
   }
}

namespace X.Y         // X.Y
{
   class E {}         // X.Y.E
}

      

 

 

 二、自动内存管理(automatic memory management)

 

      C#使用自动内存管理,这使得开发人员从手动分配和释放对象占用的内存中解脱出来专注于其它 。自动内存管理策略是由垃圾收集器实现的。对象的内存管理生命周期如下:

 

 (1)当对象创建的时候,内存为其分配空间,运行构建器,该对象被视为活(live)对象。

 

 (2)如果对象或对象的任一部分,除了运行析构函数,不能被任何可能的继续执行(continuation of execution)所访问,对象则被视为不再使用并且可以(eligible)销毁(destruction)。

 

 (3)c#编译器和gc可以选择性分析代码,来确定哪个对象引用是将来可能用到的。如下述情况,如果范围内的某本地变量是该对象唯一存在的引用,从过程(procedure)的当前执行点开始,任何可能的继续执行都不再引用该变量,则gc可以(但不是必须)视该对象不再使用。

 

 (4)一旦对象满足销毁条件,在随后的某个不确定时间,将会运行对象的析构函数(如果有的话)。除非是由显式调用覆盖,否则对象销毁只运行一次。

 

 (5)一旦运行对象的析构函数,如果那个对象或对象的任意一部分,不能被任何可能的继续执行(包括析构函数)所访问,该对象被视为不可访问,且可以销毁。

 

 (6)最后,在对象满足销毁条件后的某个时间,垃圾收集器释放关联于那个对象的内存。

 

 (7)垃圾收集器维护对象的使用信息,并且利用该信息作内存管理决策。如,在内存的何处定位一个新创建的对象,何时重定位对象,以及什么时候对象不可用或不能访问;

 

 (8)象其它假定存在gc的语言一样,C#的垃圾收集器也被设计成可以实现广泛的内存管理策略。如,c#并不要求一定要运行析构函数,不要求对象一旦满足条件就立即回收,也不要求析构函数以任何特定的顺序或以特定的线程运行;

 

 (9)通过类的System.GC静态方法,某种程度上使得gc的行为可控。该类可以用于请求一次回收、运行(或不运行)析构函数等。

 

 (10)因为gc拥有决定何时销毁对象、运行析构函数的广泛自由度,一个期望的实现(conforming implementation)可能会产生不同于原始代码的输出。 见下例

          

//以下创建A和B实例,当变量b赋值空时,对象满足析构条件
using System;
class A
{
   ~A() {
      Console.WriteLine("Destruct instance of A");
   }
}
class B
{
   object Ref;
   public B(object o) {
      Ref = o;
   }
   ~B() {
      Console.WriteLine("Destruct instance of B");
   }
}
class Test
{
   static void Main() {
      B b = new B(new A());
      b = null;
      GC.Collect();
      GC.WaitForPendingFinalizers();
   }
}

//因为语言并没有在垃圾回收的对象顺序上强加约束,故结果可能是
//Destruct instance of A
//Destruct instance of B
//也可能是
//Destruct instance of B
//Destruct instance of A

  

 (11)由于gc的灵活性、弹性,建议如下的gc策略:

           析构器只对存储在它们对象自己字段中的数据进行清除, 而不对引用的对象或静态字段执行任何操作。

 

三、执行顺序(execution order)

 

 (1)c#程序执行时,每执行线程的副作用(side effect)被保留在重要的(critical)执行点[副作用的含义是读写易失性(volatile)字段、写入非易失性变量,写入外部资源和引发异常],而且这些副作用的顺序必须被保留(preserved)在重要的执行点,后者是指引用(reference to)易失性字段、lock语句、线程创建、线程终止。

 

 (2)执行环境可自由改变C#程序的执行顺序。这归结于以下约束:

 

     a.数据依赖性保留在线程的执行当中,即,每个变量的值被计算类似(as if)线程的所有语句是以原始程序的顺序执行的;

 

     b.初始化排序规则(initialization ordering rules)被保留;

 

     c.关系到(with respect to)易失读写的副作用的顺序被保留。另外,执行环境甚至不需要计算表达式的一部分,如果它能推导出表达式的值不被使用且没有产生需要的(needed)副作用(包括,任意由调用一个方法或访问一个易变字段引起的副作用)。当程序执行被异步事件中断时(诸如其它的线程抛出异常),并不能确保可观察的副作用以原始程序顺序可见。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics