C# 语言规范--2.1 程序(转)
C# 程序由一个或多个源文件(正规地应称为编译单元(第 9.1 节))组成。源文件是有序的 Unicode 字符序列。源文件与文件系统中的文件通常具有一对一的对应关系,但这种对应关系不是必需的。为实现最大的可移植性,建议这些文件在文件系统中应按 UTF-8 规范编码。从概念上讲,程序的编译分三个步骤: 转换,这一步将用特定字符指令系统和编码方案编写的文件转换为 Unicode 字符序列。 词法分析,这一步将 Unicode 输入字符流转换为标记流。 句法分析,这一步将标记流转换为可执行代码。[@more@]
C# 语言规范--2.2.1 文法表示法(转)
词法文法和句法文法用文法产生式来表示。每个文法产生式定义一个非结束符号和它可能的扩展(由非结束符或结束符组成的序列)。在文法产生式中,非结束符号显示为斜体,而结束符号显示为等宽字体。文法产生式的第一行是该产生式所定义的非结束符号的名称,后跟一个冒号。每个后续的缩进行列出一个可能的扩展,它是以非结束符或结束符组成的序列的形式给出的。例如,产生式: while-statement:(while 语句:) while ( boolean-expression ) embedded-statement(while ( 布尔表达式 ) 嵌入语句)定义了一个 while 语句,它
C# 语言规范--1.14 属性(转)
C# 是一种命令式语言,但像所有命令式语言一样,它具有某些声明性元素。例如,通过将类中的方法声明为 public、protected、internal、protected internal 或 private,指定它的可访问性。C# 使此功能一般化,以便程序员可以创造出一种新的声明性信息,将此声明性信息附加到各种程序实体,并在运行时检索此声明性信息。程序通过定义和使用属性(第 17 节)来描述这类额外的声明性信息。例如,一个框架也许会定义一个可放置在程序元素(如类和方法)上的 HelpAttribute 属性,使开发人员能够提供从程序元素到其文档的映射。示例using System
C# 语言规范--1.13 版本控制(转)
版本控制是一个过程,它以兼容的方式对组件进行不断的改进。如果依赖于早期版本的代码重新编译后可以适用于新版本,则组件的新版本与早期版本源代码兼容。相反,如果依赖于早期版本的应用程序不用重新编译即可适用于新版本,则组件的新版本为二进制兼容。大多数语言根本不支持二进制兼容性,而且许多语言对促进源代码兼容性所做甚少。实际上,某些语言所含的缺陷使得用它开发出来的组件在不断的改进过程中,一般至少会使依赖于该组件的某些客户端代码失效。例如,请看一个发布名为 Base 的类的基类作者的情况。在第一个版本中,Base 不包含
C# 语言规范--1.11 枚举(转)
枚举类型声明为一组相关的符号常数定义了一个类型名称。枚举用于“多项选择”场合,就是程序运行时从编译时已经设定的固定数目的“选择”中做出决定。示例enum Color { Red, Blue, Green}class Shape{ public void Fill(Color color) { switch(color) { case Color.Red: ... break; case Color.Blue: ... break; case Color.Green: ... break; default: break; } }}显示了一个 Color 枚举和一个使用此
C# 语言规范--1.12 命名空间和程序集(转)
除了依赖于几个系统提供的类(如 System.Console),到目前为止介绍的程序都是独立存在的。但更常见的情况是:实际的应用程序由若干不同的部分组成,每个部分分别进行编译。例如,企业级应用程序可能依赖于若干不同的组件,其中包括某些内部开发的组件和某些从独立软件供应商处购买的组件。命名空间和程序集有助于开发基于组件的系统。命名空间提供一个逻辑组织体系。命名空间既用作程序的“内部”组织体系,也用作“外部”组织体系(一种表示向其他程序公开程序元素的途径)。程序集用于物理打包和部署。程序集可以包含类型、用于实现这些
C# 语言规范--1.10 委托(转)
委托适用于那种在某些其他语言中需用函数指针来解决的情况(场合)。但是,与函数指针不同,委托是面向对象和类型安全的。委托声明定义一个类,它是从 System.Delegate 类派生的类。委托实例封装了一个调用列表,该列表列出了一个或多个方法,每个方法称为一个可调用实体。对于实例方法,可调用实体由一个实例和该实例的方法组成。对于静态方法,可调用实体仅由一个方法组成。如果用一组合适的参数来调用一个委托实例,则该委托实例所封装的每个可调用实体都会被调用,并且用的都是上述的同一组参数。委托实例的一个有趣且有用的属性是:它
C# 语言规范--1.8 结构(转)
类与结构有很多相似之处:结构可以实现接口,并且可以具有与类相同的成员类型。然而,结构在几个重要方面不同于类:结构为值类型而不是引用类型,并且结构不支持继承。结构的值存储在“在堆栈上”或“内联”。细心的程序员有时可以通过聪明地使用结构来增强性能。例如,将 Point 定义为结构而不是类在运行时可以节省很多内存空间。下面的程序创建并初始化一个 100 点的数组。对于作为类实现的 Point,出现了 101 个实例对象,因为数组需要一个,它的 100 个元素每个都需要一个。class Point{ public int x, y; public Point(int x, in
C# 语言规范--1.9 接口(转)
一个接口定义一个协定。实现接口的类或结构必须遵守其协定。接口可以包含方法、属性、索引器和事件作为成员。示例interface IExample{ string this[int index] { get; set; } event EventHandler E; void F(int value); string P { get; set; }}public delegate void EventHandler(object sender, EventArgs e);显示了一个包含索引器、事件 E、方法 F 和属性 P 的接口。接口可以使用多重继承。在下面的示例中,interface IControl{ void Paint();}interface ITextBox: IControl{ void SetText(string text);}interface IListB
C# 语言规范--1.7 类(转)
类声明定义新的引用类型。一个类可以从另一个类继承,并且可以实现多个接口。类成员可以包括:常数、字段、方法、属性、事件、索引器、运算符、实例构造函数、析构函数、静态构造函数和嵌套类型声明。每个成员都有关联的可访问性,它控制能够访问该成员的程序文本区域。有五种可能的可访问性形式。下表概述了这些形式。publicprotectedinternalprotected internalprivate示例using System;class MyClass{ public MyClass() { Console.WriteLine("Instance constructor"); } public MyClass(int value) { MyFiel
C# 语言规范--1.6 语句(转)
C# 中的大多数语句都是直接从 C 和 C++ 借用的,但有一些值得注意的添加和修改。下表列出了可用的语句类型,并提供了每种类型的示例。static void Main() { F(); G(); { H(); I(); } }goto 语句static void Main(string[] args) { if (args.Length == 0) goto done; Console.WriteLine(args.Length);done: Console.WriteLine("Done");}static void Main() { const float pi = 3.14f; const int r = 123; Console.WriteLine(pi * r * r);}static void Main() { int a; int b = 2, c = 3; a = 1; Console.WriteLine(a + b + c);}s
C# 语言规范--1.5 表达式(转)
C# 包含一元运算符、二元运算符和一个三元运算符。下表概述了这些运算符,并将它们按优先级以从高到低的顺序列出:第 7.5 节 x.y f(x) a[x] x++ x-- newtypeof checked unchecked第 7.6 节+ - ! ~ ++x --x (T)x第 7.7 节* / %第 7.7 节+ -第 7.8 节<< >>第 7.9 节< > <= >= is as第 7.9 节== !=第 7.10 节&第 7.10 节^第 7.10 节|第 7.11 节&&第 7.11 节||第 7.12 节?:第 7.13 节= *= /= %= += -= <<= >>= &= ^= |=当表达式包含多个运算符时,运算符的优先级控制各运算符的计算顺序
C# 语言规范--1.4 自动内存管理(转)
手动内存管理要求开发人员管理内存块的分配和回收。手动内存管理可能既耗时又麻烦。在 C# 中提供了自动内存管理,使开发人员从这个繁重的任务中解脱出来。在绝大多数情况下,自动内存管理可以提高代码质量和开发人员的工作效率,并且不会对表达能力或性能造成负面影响。示例using System;public class Stack{ private Node first = null; public bool Empty { get { return (first == null); } } public object Pop() { if (first == null) throw new Exception("Can't Pop from an empty S
C# 语言规范--1.3 变量和参数(转)
变量表示存储位置。每个变量都属于一种类型,它确定什么样的值可以存储在该变量中。局部变量是在方法、属性或索引器中声明的变量。局部变量是通过指定类型名称和声明符(它指定变量名和可选的初始值)定义的,如:int a;int b = 1;但局部变量声明也可以包含多个声明符。a 和 b 的声明可以重写为:int a, b = 1;一个变量必须先赋值,然后才能使用它的值。示例class Test{ static void Main() { int a; int b = 1; int c = a + b; // error, a not yet assigned ... }}导致编译时错误,因为它试图在给变量 a 赋值
C# 语言规范--1.2 类型(转)
C# 支持两种类型:“值类型”和“引用类型”。值类型包括简单类型(如 char、int 和 float)、枚举类型和结构类型。引用类型包括类 (Class) 类型、接口类型、委托类型和数组类型。值类型与引用类型的区别在于值类型的变量直接包含其数据,而引用类型的变量则存储对象引用。对于引用类型,两个变量可能引用同一对象,因此对一个变量的操作可能影响另一个变量所引用的对象。对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响另一个变量。示例using System;class Class1{ public int Value = 0;}class Test{ static v
C# 程序员参考--索引器教程(转)
本教程展示 C# 类如何声明索引器以提供对类的类似数组的访问。示例文件请参见“索引器”示例以下载和生成本教程中讨论的示例文件。教程定义“索引器”使您可以创建作为“虚拟数组”的类。该类的实例可以使用 [] 数组访问运算符进行访问。在 C# 中定义索引器类似于在 C++ 中定义运算符 [],但前者灵活得多。对于封装类似数组的功能或类似集合的功能的类,使用索引器使该类的用户可以使用数组语法访问该类。例如,假定您想定义一个类,该类使文件显示为字节数组。如果文件非常大,则将整个文件读入内存是不切实际的,尤其在您只想读取或更改
C# 程序员参考--用户定义的转换教程(转)
本教程展示如何定义转换以及如何在类或结构之间使用转换。示例文件请参见“用户定义的转换”示例以下载和生成本教程中讨论的示例文件。教程C# 允许程序员在类或结构上声明转换,以便可以使类或结构与其他类或结构或者基本类型相互进行转换。转换的定义方法类似于运算符,并根据它们所转换到的类型命名。在 C# 中,可以将转换声明为 implicit(需要时自动转换)或 explicit(需要调用转换)。所有转换都必须为 static,并且必须采用在其上定义转换的类型,或返回该类型。本教程介绍两个示例。第一个示例展示如何声明和使用转换,第二个示例
C# 程序员参考--库教程(转)
本教程展示如何在 C# 中创建和使用库。教程本教程演示如何使用必要的编译器选项创建托管 DLL 文件,以及如何通过客户程序使用该库。示例本示例使用下列模块: DLL 库 (Functions.dll),从以下源文件生成: Factorial.cs:计算并返回某数的阶乘。 DigitCounter.cs:计算所传递的字符串中的数字位数。使用该 DLL 的客户程序 (FunctionTest.exe),从源文件 FunctionClient.cs 进行编译。本程序显示输入参数的阶乘。生成库若要生成该库,请将 Functions 作为当前目录,并在命令提示处键入下列内容:csc /target:library /out:Functions.dll Fa
C# 程序员参考--数组教程二(转)
示例 下面是一个完整的 C# 程序,它声明并实例化上面所讨论的数组。 // arrays.cs using System; class DeclareArraysSample { public static void Main() { // Single-dimensional array int[] numbers = new int[5]; // Multidimensional array string[,] names = new string[5,4]; // Array-of-arrays (jagged array) byte[][] scores = new byte[5][];
C# 程序员参考--数组教程三(转)
多维数组 int[,] numbers = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} }; string[,] siblings = new string[2, 2] { {"Mike","Amy"}, {"Mary","Albert"} }; 可省略数组的大小,如下所示: int[,] numbers = new int[,] { {1, 2}, {3, 4}, {5, 6} }; string[,] siblings = new string[,] { {"Mike","Amy"}, {"Mary","Albert"} }; 如果提供了初始值设定项,则还可以省略 new 运算符,如下所示: