1、C# 声明C# 程序中的声明定义程序的构成元素。一个声明在它自已所属的那个声明空间 (declaration space) 中定义一个名称。除非是重载成员,否则,在同一个声明空间下若有两个以上的声明语句声明了具有相同名称的成员,就会产生编译时错误。有若干种不同类型的声明空间,每个声明空间的成员对于相应的作用域如下所述。1. 在程序的所有源文件中,成员的空间声明若没有被置于任何一个空间声明下,则属于一个称为全局声明空间(global declaration space) 的组合声明空间。2. 程序的所有源文件中,一个成员的空间声明若在空间声明中具有相同的完全限定的命名空间名称,它就属于一个组合声
2、明空间。3. 每个类、结构或接口声明创建一个新的声明空间。除了重载实例构造函数声明和静态构造函数声明外,类或结构成员声明不能引入与该类或结构同名的成员。4. 每个委托声明创建一个新的声明空间。名称通过形参(固定参数和 参数数组)和类型参数引入此声明空间。5. 每个枚举声明创建一个新的声明空间。名称通过枚举成员的声明引入此声明空间。6. 每个方法声明、索引器声明、运算符声明、实例构造函数声明和匿名函数均创建一个称为局部变量声明空间的新声明空间。7. 将函数成员或匿名函数的体(如果有)视为嵌套在局部变量声明空间中。如果局部变量声明空间和嵌套的局部变量声明空间包含具有相同名称的元素,则会发生错误。因
3、此,在嵌套声明空间中不可能声明与封闭它的声明空间中的局部变量或常量同名的局部变量或常量。只要两个声明空间彼此互不包含,这两个声明空间就可以包含同名的元素。8. 每个 block 或 switch-block 以及 for、foreach 和 using 语句都会为局部变量和局部常量 创建一个局部变量声明空间。名称通过 局部变量声明 和 局部常量声明 引入此声明空间。请注意,作为函数成员的体或匿名函数的体出现或出现在该体之中的块嵌套在由这些函数为其参数声明的局部变量声明空间中。因此,如果某个方法的局部变量和参数具有相同名称,则会发生错误。9. 每个 block 或 switch-block 都为
4、标签创建一个单独的声明空间。名称通过标签声明引入此声明空间,通过 goto-statements 语句被引用。块的标签声明空间 (label declaration space) 包含任何嵌套块。因此,在嵌套块中不可能声明与封闭它的块中的标签同名的标签。C# 成员命名空间和类型具有成员 (member)。通常可以通过限定名来访问实体的成员。限定名以对实体的引用开头,后跟一个“.”标记,再接成员的名称。类型的成员或者是在该类型声明中声明的,或者是从该类型的基类继承 (inherit) 的。1. 命名空间的成员:命名空间和类型若没有封闭它的命名空间,则属于全局命名空间 (global namesp
5、ace) 成员。直接对应于全局声明空间中声明的名称在某命名空间中声明的命名空间和类型是该命名空间的成员。直接对应于该命名空间的声明空间中声明的名称。命名空间没有访问限制。不可能把命名空间设置成私有的、受保护的或内部的,命名空间名称始终是可公开访问的。2. 结构的成员:是在结构中声明的成员以及继承自结构的直接基类 System.ValueType 和间接基类 object 的成员。3. 枚举的成员:是在枚举中声明的常量以及继承自枚举的直接基类 System.Enum 和间接基类 System.ValueType 和 object 的成员。4. 类的成员:是在类中声明的成员和从该类的基类(没有基类
6、的 object 类除外)继承的成员。从基类继承的成员包括基类的常量、字段、方法、属性、事件、索引器、运算符和类型,但不包括基类的实例构造函数、析构函数和静态构造函数。基类成员被是否继承与它们的可访问性无关。5. 接口的成员:是在接口中和该接口的所有基接口中声明的成员。严格地说,类 object 中的成员不是任何接口的成员。但是,通过在任何接口类型中进行成员查找,可获得类 object 中的成员6. 数组的成员:是从类 System.Array 继承的成员。7. 委托的成员:是从类 System.Delegate 继承的成员。C# 成员访问成员的声明可用于控制对该成员的访问。成员的可访问性是由
7、该成员的声明可访问性和直接包含它的那个类型的可访问性结合起来确定的。成员的已声明可访问性 (declared accessibility) 可以是下列类型之一:1. Public:选择它的方法是在成员声明中包括 public 修饰符。public 的直观含义是“访问不受限制2. Protected:选择它的方法是在成员声明中包括 protected 修饰符。protected 的直观含义是“访问范围限定于它所属的类或从该类派生的类型”。3. Internal:选择它的方法是在成员声明中包括 internal 修饰符。internal 的直观含义是“访问范围限定于此程序”。4. Protecte
8、d internal:选择它的方法是在成员声明中包括 protected 和 internal 修饰符。protected internal 的直观含义是“访问范围限定于此程序或那些由它所属的类派生的类型”。5. Private:选择它的方法是在成员声明中包括 private 修饰符。private 的直观含义是“访问范围限定于它所属的类型”。声明一个成员时所能选择的已声明可访问性的类型,依赖于该成员声明出现处的上下文。此外,当成员声明不包含任何访问修饰符时,声明发生处的上下文会为该成员选择一个默认的已声明可访问性。1. 命名空间隐式地具有 public 已声明可访问性。在命名空间声明中不允许
9、使用访问修饰符。2. 编译单元或命名空间中声明的类型可以具有 public 或 internal 已声明可访问性,默认的已声明可访问性为 internal。3. 类成员可具有五种已声明可访问性中的任何一种,默认为 private 已声明可访问性。4. 结构成员可以具有 public、public 或 private 已声明可访问性并默认为 private 已声明可访问性。5. 接口成员隐式地具有 public 已声明可访问性。在接口成员声明中不允许使用访问修饰符。6. 枚举成员隐式地具有 public 已声明可访问性。在枚举成员声明中不允许使用访问修饰符。C# 类型1. C# 中的类型有两种:
10、值类型 (value type) 和引用类型 (reference type)。值类型的变量直接包含它们的数据,而引用类型的变量存储对它们的数据的引用,后者称为对象。1) 对于引用类型,两个变量可能引用同一个对象,因此对一个变量的操作可能影响另一个变量所引用的对象。2) 对于值类型,每个变量都有它们自己的数据副本(除 ref 和 out 参数变量外),因此对一个变量的操作不可能影响另一个变量。2. 在程序编码中一些包含类型参数的类型成为泛型类型(generic type),也就是说泛型的参数只可以代表类,不能代表个别对象。值类型和引用类型都可以为泛型类型,泛型类型采用一个或多个类型参数。类型参
11、数可以指定值类型和引用类型。3. C# 的类型系统是统一的,因此任何类型的值都可以按对象处理。C# 中的每个类型直接或间接地从 object 类类型派生,而 object 是所有类型的最终基类。引用类型的值都被视为 object 类型,被简单地当作对象来处理。值类型的值则通过对其执行装箱和拆箱操作按对象处理。C# 值类型1. C# 的值类型进一步划分为简单类型 (simple type)、枚举类型 (enum type)、结构类型 (struct type) 和可以为 null 的类型 (nullable type)2. 所有值类型从类 System.ValueType 隐式继承,后者又从类
12、object 继承。任何类型都不可能从值类型派生,因此,所有值类型都是隐式密封的。3. 所有值类型都隐式声明一个称为默认构造函数 (default constructor) 的公共无参数实例构造函数。与任何其他实例构造函数一样,值类型的默认构造函数也是用 new 运算符调用的。出于效率原因,实际上,不必故意调用它的构造函数。4. 默认构造函数返回一个零初始化实例,它就是该值类型的默认值 (default value)1) 对于所有简单值类型(simple type),默认值是由所有位都置零的位模式产生的值:i. 对于 sbyte、byte、byte、ushort、int、uint、long 和
13、 ulong,默认值为 0。ii. 对于 char,默认值为 x0000。iii. 对于 float,默认值为 0.0f。iv. 对于 double,默认值为 0.0d。v. 对于 decimal,默认值为 0.0m。vi. 对于 bool,默认值为 false。2) 对于枚举类型(enum type)E,默认值为 0,该值被转换为类型 E。3) 对于 结构类型(struct type),默认值是通过将所有值类型字段设置为默认值并将所有引用类型字段设置为 null 而产生的值。4) 对于 可以为 null 的类型(nullable type),默认值是一个其 HasValue 属性为 fals
14、e 且 Value 属性未定义的实例。默认值也称为可以为 null 的类型的 null 值 (null value)。5. 结构类型(struct type)可以声明常量、字段、方法、属性、索引器、运算符、实例构造函数、静态构造函数和嵌套类型。6. 简单类型(simple type) 通过保留字标识,而这些保留字只是 System 命名空间中预定义结构类型的别名可细分为如下几类:1) 有符号整型:sbyte、short、int 和 long2) 无符号整型:byte、ushort、uint 和 ulong3) Unicode 字符型:char4) IEEE 浮点型:float 和 double
15、5) 高精度小数型:decimal6) 布尔型:bool7. 由于简单类型是结构类型的别名,每个简单类型都具有成员。简单类型与其他结构类型的不同之处在于,简单类型允许某些附加的操作:1) 大多数简单类型允许通过编写文本来创建值。1) 当表达式的操作数都是简单类型常量时,编译器可以在编译时计算表达式。这样的表达式称为常量表达式。涉及其他结构类型所定义的运算符的表达式不被视为常量表达式。2) 通过 const 声明可以声明简单类型的常量。常量不可能属于其他结构类型,但 static readonly 字段提供了类似的效果。2) 涉及简单类型的转换可以参与由其他结构类型定义的转换运算符的计算,但用户
16、定义的转换运算符永远不能参与其他用户定义运算符的计算8. 枚举类型(enum type)是具有命名常量的独特的类型。每个枚举类型都有一个基础类型,该基础类型必须为 byte、sbyte、short、ushort、int、uint、long 或 ulong。枚举类型的值集和它的基础类型的值集相同。枚举类型的值并不只限于那些命名常量的值。9. 可以为 null 的类型(nullable type)可以表示其基础类型 (underlying type) 的所有值和一个额外的 null 值。可以为 null 的类型写作 T?,其中 T 是基础类型。此语法是 System.Nullable 的简写形式,
17、这两种形式可以互换使用。1) 可以为 null 的类型 T? 的实例有两个公共只读属性:i. 类型为 bool 的 HasValue 属性ii. 类型为 T 的 Value 属性2) 除了默认构造函数之外,每个可以为 null 的类型 T? 都有一个具有类型为 T 的单个实参的公共构造函数。例如,给定一个类型为 T 的值 x,调用形如new T?(x) 的构造函数将创建 T? 的非 null 实例,其 Value 属性为 x。3) 为一个给定值创建可以为 null 的类型的非 null 实例的过程称作包装 (wrapping)。C# 引用类型1. C# 的引用类型进一步划分为类类型 (clas
18、s type)、接口类型 (interface type)、数组类型 (array type) 和委托类型 (delegate type)。2. 引用类型值是对该类型的某个实例 (instance) 的一个引用,后者称为对象 (object)。null 值比较特别,它兼容于所有引用类型,用来表示“没有被引用的实例”。3. 类类型 (class type)定义包含数据成员、函数成员和嵌套类型的数据结构,其中数据成员包括常量和字段,函数成员包括方法、属性、事件、索引器、运算符、实例构造函数、析构函数和静态构造函数。类类型支持继承,继承是派生类可用来扩展和专门化基类的一种机制。类类型的实例是用对象创
19、建表达式创建的。1) 某些预定义类类型在 C# 语言中有特殊含义,如下表所示。类类型说明System.Object所有其他类型的最终基类。System.StringC# 语言的字符串类型。System.ValueType所有值类型的基类。System.Enum所有枚举类型的基类。System.Array所有数组类型的基类。System.Delegate所有委托类型的基类。System.Exception所有异常类型的基类。2) object 类类型是所有其他类型的最终基类。C# 中的每种类型都是直接或间接从 object 类类型派生的。关键字 object 只是预定义类 System.Obje
20、ct 的别名。3) dynamic 类型与 object 一样,可以引用任何对象。在将运算符应用于 dynamic 类型的表达式时,其解析会推迟到程序运行时进行。因此,如果运算符不能合法地应用于引用的对象,在编译过程中不会报告任何错误。而是在运行时解析运算符失败时,会引发异常。4) string 类型是直接从 object 继承的密封类类型。string 类的实例表示 Unicode 字符串。4. 接口类型 (interface type):一个接口定义一个协定。实现某接口的类或结构必须遵守该接口定义的协定。一个接口可以从多个基接口继承,而一个类或结构可以实现多个接口。5. 数组类型 (arr
21、ay type):数组是一种数据结构,它包含可通过计算索引访问的零个或更多个变量。数组中包含的变量(又称数组的元素)具有相同的类型,该类型称为数组的元素类型。6. 委托类型 (delegate type):委托是引用一个或多个方法的数据结构。1) 对于实例方法,委托还可引用实例方法对应的对象实例。2) 在 C 或 C+ 中与委托最接近的是函数指针,但函数指针只能引用静态函数,而委托则既可以引用静态方法,也可以引用实例方法。在后一种情况中,委托不仅存储了一个对该方法入口点的引用,还存储了一个对相应的对象实例的引用,该方法就是通过此对象实例被调用的。C# 装箱和拆箱1. 装箱和拆箱的概念是 C#
22、类型系统核心。装箱和拆箱在值类型和引用类型之间架起了一座桥梁,使得任何 value-type 的值都可以转换为 object 类型的值,反过来转换也可以。装箱和拆箱使我们能够统一地来考察类型系统,其中任何类型的值最终都可以按对象处理。2. 装箱(boxing)转换允许将 值类型 隐式转换为 引用类型。装箱转换隐含着复制一份待装箱的值。这不同于从 reference-type 到 object 类型的转换,在后一种转换中,转换后的值继续引用同一实例,只是将它当作派生程度较小的 object 类型而已。存在下列装箱转换:1) 从任何 值类型到 object 类型。2) 从任何 值类型 到 Syst
23、em.ValueType 类型。3) 从任何 不可以为ull值 到值类型实现的任何接口类型。4) 从任何可以为null值 到由 可以为null值 的基础类型实现的任何接口类型。5) 从任何 枚举类型 到 System.Enum 类型。6) 从任何具有基础枚举类型的 可以为null值 到 System.Enum 类型。3. 拆箱(unboxing)转换允许将引用类型显式转换为值类型。存在以下拆箱转换:1) 从 object 类型到任何值类型。2) 从 System.ValueType 类型到任何值类型。3) 从任何接口类型到实现了该接口类型的任何不可以为空的值。4) 从任何接口类型到其基础类型实
24、现了该接口类型的任何可以为空的值。5) 从 System.Enum 类型到任何枚举类型。6) 从 System.Enum 类型到任何具有基础枚举类型的可以为空的值。C# 表达树类型1. 表达式树 (Expression tree) 允许匿名函数表示为数据结构而不是可执行代码。表达式树是匿名函数有效的内存数据表示形式,它使匿名函数的结构变得透明和明晰。表达式树是 System.Linq.Expressions.Expression 形式的表达式树类型 (expression tree type) 的值。2. 如果存在从匿名函数到委托类型 D 的转换,则也存在到表达式树类型 Expression
25、的转换。与委托类型 D 一样,Expression 具有与 D 相同的参数和返回类型。3. 并非所有匿名函数都能表示为表达式树。例如,具有语句体的匿名函数和包含赋值表达式的匿名函数就不能表示为表达式树。在这些情况下,转换仍存在,但在编译时将失败。Expression 提供一个实例方法 Compile,该方法产生一个类型为 D 的委托下面的示例将匿名函数表示为可执行代码和表达式树。Func del = x = x + 1; /匿名函数委托 exp = x = /类型转换 del2 = exp.Compile(); /编译int i1 = del(1); int i2 = del2(1);执行此代
26、码后,i1 和 i2 的值都为 2。C# 类型声明在 C# 类型分类中,有五类是用户可定义的:1. 类类型 (class type):类类型定义了一个包含数据成员(字段)和函数成员(方法、属性等)的数据结构。类类型支持单一继承和多态,这些是派生类可用来扩展和专用化基类的机制。2. 结构类型 (struct type):结构类型与类类型相似,表示一个带有数据成员和函数成员的结构。但是,与类不同,结构是一种值类型,并且不需要堆分配。结构类型不支持用户指定的继承,并且所有结构类型都隐式地从类型 object 继承。3. 接口类型 (interface type):接口类型定义了一个协定,作为一个公共
27、函数成员的命名集。实现某个接口的类或结构必须提供该接口的函数成员的实现。4. 枚举类型 (enum type) :枚举类型是具有命名常量的独特的类型。每种枚举类型都具有一个基础类型,该基础类型必须是八种整型之一。5. 委托类型 (delegate type):委托类型表示对具有特定参数列表和返回类型的方法的引用。通过委托,我们能够将方法作为实体赋值给变量和作为参数传递。委托类似于在其他某些语言中的函数指针概念,但是与函数指针不同,委托是面向对象的,并且是类型安全的C# 变量1. 变量表示存储位置。每个变量都具有一个类型,用于确定哪些值可以存储在该变量中。2. C# 是一种类型安全的语言,C# 编译器保证存储在变量中的值总是具有合适的类型。3. C# 定义了 7 类变量:静态变量、实例变量、数组元素、值参数
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1