• 第十六章 代码组织与管理


      本章介绍C#语言所特有的一些代码特性,包括用于源代码分散管理的分布类型(Partial Type)、用于代码编译管理的预处理器指令,以及支持软件文档生成的XML代码注释。

    1 分布类型

      有时候在一个类的定义中可能包含大量的字段和方法成员,甚至大量的嵌套类型,导致代码行数太多,管理起来很不方便。为此,C#中提供了分布类型概念,允许将一个类的定义分散到多个代码片段之中,而这些代码片段又可以放在不同的源文件中。采用这种方式定义的类叫做分布类。分布类型同样适用于结构和接口,所定义的类型分别叫做分布结构和分布接口。

    1.1 分布类型的定义

      分布类型通过修饰符partial进行定义,该修饰符可以出现在关键字class、struct和interface之前,用于定义不同的分布类型,例如:

    public partial interface IOutput{}
    public partial class Contact{}
    public partial struct Table{}

      由于类的名称相同,下面两段代码共同组成了一个分布类Contact的定义:

    public partial class Contact
    {
        private string m_name;
    }
    
    public partial class Contact
    {
        private string m_gender;
    }

      一旦某个类型被定义为分布类型,那么在其每一部分的定义中都必须使用partial修饰符。这些部分可以在不同的源文件中,但有以下要求:

      • 各部分使用的访问限制修饰符应当相同;

      • 各部分不能包含重复的成员的定义,除非该成员属于嵌套的分布类型;

      • 各部分不能定义不同的基类

      • 它们所在的命名空间的名称必须相同,否则就是分属于不同的程序集的不同类型;

      • 它们所分布的各个源文件必须在一起编译。

      和访问限制修饰符不同,只要在分布类型的任何部分的定义中使用了abstract或sealed修饰符(注意这两个修饰符不能同时出现),那么该类型就是抽象类型或密封类型。

      不允许在分布类型的不同部分定义不同的基类。但对于接口则没有这个限制,所有部有继承的接口(可以重复出现)共同组成了整个分布类型继承的接口。

      可以将嵌套类型也定义为分布的,这时有两种情况:

      一是嵌套类型所在的外部类型不是分布类型,那么其各部分定义就必须全部在外部类型的当前定义中,例如:

    public class Contact
    {
        public partial class ChangeEventArgs : EventArgs
        {
            ...
        }
        
        public partial class ChangeEventArgs
        {
            ...
        }
    }

      二是嵌套类型所在的外部类型也是分布类型,那么其各部分定义也可以分布在外部类型的不同部分当中,其它要求和一般的分布类型相同,例如:

    public partial class Contact
    {
        ...
        public partial class ChangeEventArgs : EventArgs
        {
            ...
        }
    }
    
    public partial class Contact
    {
        ...
        public partial class ChangeEventArgs
        {
            ...
        }
    }

    1.2 分布泛型

      泛型类型采用分布类型的定义方式,必须满足对一般分布类型的定义要求。由于泛型的特殊性,分布的泛型在类型参数的使用上还有下列附加规则:

       • 泛型的类型参数在每个部分都需要进行声明,而且数量和名称必须完全相同;

       • 如果在部分定义中出现了类型限制,这就是对整个泛型的类型限制;

       • 如果多个部分定义中都现出了类型限制,那么这些限制必须相同(包括继承限制和构造函数限制),但对书写的次序没有要求;

    2 代码中的预处理器指令

    2.1 条件编译

      先看下面的程序:

    #define Detail
    using System;
    
    namespace P18_5
    {
        class PreprocessSample
        {
            static void Main()
            {
                Console.WriteLine("请输入1~50之间的一个整数:");
                int n;
                while (!int.TryParse(Console.ReadLine(), out n) || n < 1 || n > 50)
                {
                    Console.WriteLine("请输入1~50之间的一个整数:");
                }
                if (n == 1)
                {
                    Console.WriteLine("FB(1) = 1");
                    return;
                }
                long l1 = 1, l2 = 2, lTmp;
    #if(Detail)
                {
                for (int i = 1; i < n - 1; i++)
                {
                    lTmp = 12;
                    l2 = l2 + l1;
                    Console.WriteLine("FB({0}) = {1} + {2} = {3}", i + 2, l1, lTmp, l2);
                    l1 = lTmp;
                }
                }
    #else
                {
                for (int i = 1; i < n - 1; i++)
                {
                    lTmp = 12;
                    l2 = l2 + l1;
                    l1 = lTmp;
                }
                }
    #endif
                Console.WriteLine("运算结果:FB({0})= {1}", n, l2);
            }
        }
    }

       运行结果为:

    请输入1~50之间的一个整数:
    30
    FB(3) = 1 + 12 = 3
    FB(4) = 12 + 12 = 15
    FB(5) = 12 + 12 = 27
    FB(6) = 12 + 12 = 39
    FB(7) = 12 + 12 = 51
    FB(8) = 12 + 12 = 63
    FB(9) = 12 + 12 = 75
    FB(10) = 12 + 12 = 87
    FB(11) = 12 + 12 = 99
    FB(12) = 12 + 12 = 111
    FB(13) = 12 + 12 = 123
    FB(14) = 12 + 12 = 135
    FB(15) = 12 + 12 = 147
    FB(16) = 12 + 12 = 159
    FB(17) = 12 + 12 = 171
    FB(18) = 12 + 12 = 183
    FB(19) = 12 + 12 = 195
    FB(20) = 12 + 12 = 207
    FB(21) = 12 + 12 = 219
    FB(22) = 12 + 12 = 231
    FB(23) = 12 + 12 = 243
    FB(24) = 12 + 12 = 255
    FB(25) = 12 + 12 = 267
    FB(26) = 12 + 12 = 279
    FB(27) = 12 + 12 = 291
    FB(28) = 12 + 12 = 303
    FB(29) = 12 + 12 = 315
    FB(30) = 12 + 12 = 327
    运算结果:FB(30)= 327
    请按任意键继续. . .

      注意程序的第一行代码:

    #define Detail

      这是一个预处理指令,它为程序定义了一个名为Detail的标识符。而程序主方法中出现的#if-#else-#endif语句是一个条件编译语句,它根据程序是否存在标识符Detail来选择要编译的代码。如果把程序第一行的预处理器指令去掉,输出结果为:

    请输入1~50之间的一个整数:
    30
    运算结果:FB(30)= 327
    请按任意键继续. . .

    2.1.1 #define和#undef指令

      它们叫做标识符定义指令,分别用于定义和取消标识符,使用时后跟标识符的名称。#define和#undef必须出现在所有代码之前(不包括注释)。例如,可以在程序P18_5.CS中再插入一条#undef指令,这样就取消了#define指令结标识符Detail的定义,程序将不显示详细的计算过程:

    #define Detail
    #undef Detail

      标识符只是一个编译符号,和变量没有变量。在程序中可以定义一个变量Detail,并不会和标识符Detail产生命名冲突。

    2.1.2 #if、#else、#elif和#endif指令

      它们都叫做条件编译指令。在使用时,#if和#elif指令后跟标识符表达式。标识符表达式可以是单个标识符,还可以是通过与操作符“&&”以及或操作符“||”进行连接的多个标识符。

      条件编译指令可以组成3种结构

      (1)#if-#endif结构

      (2)#if-#else-#endif结构

      (3)#if-#elif-#else-#endif结构

    2.2 编译警告和错误

    2.2.1 #warning指令

      当所在代码被编译时,#warning指令生成一条警告信息。它使用时后跟要输出的警告内容。使用C#编译器时,可以通地编译选项“/nowarn”来关闭警告信息的显示.

      例如,下面的程序在编译时会生成警告信息“正在使用控制台应用程序”:

    class PreprocessSample
    {
        static void Main()
        {
    #warning 正在使用控制台应用程序
            //
        }
    }

    2.2.2 #error指令

      当所在的代码被编译时,#error指令生成一条错误信息。它使用时后跟要输出的错误内容。与#warning指令不同的是,#error指令的执行会导致编译的失败。

    2.2.3 其它预处理指令

      • #region和#endregion,二者配套使用,支持代码区域的折叠和展开。

      • #line指令,用于指定代码所在的行数

      • #pragma指令,要求编译器使用指定的指令来编译源程序

      • #pragma warning指令,用于在编译时打或关闭指定的警告信息。

    3 XML代码注释

      如果程序中的代码注释符合特定的XML语法规则,那么在将代码编译成程序的同时,还能够根据这些注释内容生成对应的XML软件文档。

    3.1 XML简介

      XML的中文译法叫做可扩展标记语言(eXtensible Markup Language),是一个格式独立的,与平台和应用无关的语言。

    3.2 使用XML注释

            /// <summary>
            /// 主方法
            /// </summary>
            static void Main(){}
  • 相关阅读:
    hdu 3047 Zjnu Stadium(加权并查集)2009 Multi-University Training Contest 14
    hdu 5407 CRB and Candies(组合数+最小公倍数+素数表+逆元)2015 Multi-University Training Contest 10
    hdu 3635 Dragon Balls(加权并查集)2010 ACM-ICPC Multi-University Training Contest(19)
    hdu 3038 How Many Answers Are Wrong(种类并查集)2009 Multi-University Training Contest 13
    【进阶——种类并查集】hdu 1829 A Bug's Life (基础种类并查集)TUD Programming Contest 2005, Darmstadt, Germany
    hdu 1026 Ignatius and the Princess I(优先队列+bfs+记录路径)
    hdu2368Alfredo's Pizza Restaurant
    C#结课报告
    C#三个平台上的文件选择方法
    C#线程
  • 原文地址:https://www.cnblogs.com/boywg/p/4149980.html
Copyright © 2020-2023  润新知