快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

.NET中的特别类型成员----微软 .NET平台系列文章之三(译文/赵湘宁)

 
.NET中的特别类型成员

----微软 .NET平台系列文章之三

译文/赵湘宁
在前面的两篇文章中,我们研究了类型的基础知识。本文我们将考察类型能定义的某些特别成员。在大力简化处理类型及其对象实例需要的语法方面,这些类型有助于面向对象设计

类型构造器
    你已经认识了什么是构造器,它负责对象实例状态的初始化。除了实例构造器以外,Microsoft(r).NET公共语言运行时(CLR)还支持类型构造器(也叫做静态构造器、类构造器或类型初始化)。类型构造器可被应用到接口,类和数值类型。它答应任何在类型中声明的成员被访问之前实现必要的初始化。类型构造器不需要参数并且总是返回void类型。类型构造器只访问类型的静态字段并且其通常的目的是初始化这些字段。在类型的任何实例被创建之前以及类型的任何静态字段或方式被引用之前,必须要保证已经运行了类型构造器。
许多语言(包括C#)在定义类型时都自动产生类型构造器。但是某些语言需要显式(手工)实现类型构造器。
为了理解类型构造器,让我们研究一下列在C#中定义的类型:

class Atype {
static int x = 5;
}

    在建立这个代码时,编译器自动地为产生Atype类型构造器。这个构造器负责初始化静态字段x为值5。假如你使用ILDasm,很轻易认出类型构造器方式,因为它们的名字都是.cctor(对于类构造器而言)。
    在C#中,通过在类型中定义静态构造器方式,你可以自己实现类型构造器。要害字static的使用意味着这时类型构造器,而不是实例构造器。下面是一个异常简朴的例子:

class AType {
static int x;

static AType() {
x = 5;
}
}

    这个类型定义与前面的一样。注重类型构造器决不能试图创建自己的类型实例,而且构造器也不能引用类型的非静态成员。
最后,假如你用C#编译器编译下列代码,它产生单独的类型构造器方式:

class AType {
static int x = 5;

static AType() {
x = 10;
}
}

    这个构造器首先初始化x=5,然后,初始化x=10。换句话说,编译器产生的结果类型构造器首先包含静态字段的初始化代码,随后是类型构造器的代码。

属性
    许多类型定义的属性可以被重新获得或修改。这些属性经常都是用类型字段成员来实现的。例如,下面是包含有两个字段的类型定义:

class Employee {
public String Name;
public Int32 Age;
}

假如创建这个类型的实例,那么很轻易用以下代码得到或设置属性:

Employee e = new Employee();
e.Name = "Jeffrey Richter"; // 设置名字属性
e.Age = 36; // 设置年龄属性

Console.WriteLine(e.Name); // 显示 "Jeffrey Richter"

    用这种方法使用属性异常普通。但以我的观点看,上述代码不会向列出的那样被实现。面向对象设计和编程的立约之一便是数据抽象。它的意思就时类型字段不能用公共字段暴露出来,因为它太轻易被修改,太轻易让人写出不恰当地使用这个字段的代码,从而破坏对象的状态。例如,某人很轻易编写下面的代码破坏Employee对象:

e.Age = -5; //人的年龄怎么会是-5呢?

所以说,在设计类型时,我强烈建议所有字段都是私有的(private)或至少是受保护的(protected)――决不要公共的(public)。然后,让使用类型的人能Get或Set属性,专门为此提供方式。打包对字段的访问的方式就叫做存取器(或访问器方式)方式。这些方式能随时实现完整性检查并保证对象的状态不被破坏。例如,我重写了前面定义过的Employee类,代码如图一。虽然这是一个简朴的例子,但你能从中明白抽象数据字段的巨大好处,你还能从中明白如何轻松实现只读属性,或者仅仅通过不去实现某个存取器方式来轻松达到只写属性。
    图一中显示的数据抽象方式有两个缺点。第一,因为要实现附加的函数,所以要多写一些代码。第二,类型的使用者现在必须要调用方式而不是仅仅引用单个的字段名:

e.SetAge(36); // Updates the age
e.SetAge(-5); // Throws an exception

    我想,所有的人都会同意这些缺点与其长处比起来显得微不足道,但运行时仍旧提供了一种属性机制,多少使得第一个缺点轻易忍受了,并且完全消除了第二个缺点。
    图二中的类使用了属性,其功能和图一所示的类一样。正如你所看到的,属性简化了一些代码,但更重要的是答应调用这项下面相同写自己的代码:

.Age = 36; // 更新年龄
e.Age = -5; // 掷出非常Throws an exception

    Get属性存取器的返回值和传递到Set属性存取器参数值类型一样。Set属性存取器的返回值是void,而Get属性存取器没有入口参数。属性可以是静态的、虚拟的、抽象的、内部的、私有的、保护的或公共的。另外,属性可以在接口中定义,关于这一点将在后面讨论。
    我还应该指出属性不必于字段关联。例如,类型System.IO.FileStream定义了一个长度属性,它返回流中的字节数。当长度属性的Get方式被调用时,这个长度不是由字段提供,而是调用另一个函数哀求底层操作系统返回打开文件流的字节数。
    当你创建属性时,编译器实际上发出专门的get_ProName和/或set_ProName存取器方式(这里ProName是属性名)。大多数编译器会理解这些专用方式并答应开发人员存取这些有专门属性语法的方式。但是,遵守公共语言运行时规范的编译器不需要完全支持属性,只要支持专用存取方式调用即可。
    另外,对于完全支持属性的编译器来说,在定义和使用属性时使用的语法稍有不同,例如带受管扩展的C++需要使用_property要害字。

索引属性
    某些类型,如System.Collections.SortedList暴露逻辑元素列表。为了能轻松存取这种类型中的元素,可以定义一个索引属性(也叫索引器-indexer)。图三显示的是一个索引属性的例子,其索引器的的使用极其简朴:

BitArray ba = new BitArray(14);
for (int x = 0; x < 14; x++) {
// 置所有偶数位为“on”
ba[x] = (x % 2 == 0);
Console.WriteLine("Bit " + x + " is " + (ba[x] ? "On" : "Off"));
}

图三的BitArray例子中,索引器带一个Int32参数:bitPosition。索引器必须至少带一个参数,参数个数可以是两个或更多。这些参数(以及返回类型)可以是任何类型。创建以String作为参数的索引器查找联合数组中的值是十分普通的事情。一种类型可以提供多个索引器,只要其原型不同。
    就像set属性,set索引器存取方式包含一个隐藏的参数,值,当存取方式被调用时,它表示想得到一个新的值。BitArray的set存取方式显示了这个参数值的使用。

    一个设计良好的索引器应该具备get和set两个存取方式。即便你能只实现get存取方式(对于只读语义)或者只实现set存取方式(对于只写语义),建议你的索引器实现两个存取器。理由很简朴,索引的使用者不希望只有半个行为。例如,当编写下面两行代码时,使用者不想看到编译器出错:
String s = SomeObj[5]; // 假如有存取器,编译 OK
SomeObj[5] = s; //假如没有存取器,编译出错

    索引器总是起类型实例的作用,并且不能被声明为静态。但它可以是公共的、私有的、保护的或内部的。
    当你创建索引属性时,编译器实际上会发布专门的get_Item和/或set_Item存取器方式。大多数编译器都会理解这些专门的方式并且会答应开发人员利用专门的索引属性语法存取这些方式。但是,与CLS(公共语言系统)兼容的编译器不需要完全支持索引属性;只要编译器支持专用存取器调用即可。
    同样,对于完全支持索引属性的编译器在定义和使用这些属性的时候,需要的语法稍有差别。例如,C++受管扩展需要使用_property要害字。

结论
    本文中所讨论的概念对于所有.NET的程序员来说极其重要。我所提到的特别的类型成员使组件成为公共语言运行时最重要的内容。也就是说,现代组件被设计成支持属性。
下一篇文章我将介绍委派和事件成员,因为它们与基于组件的应用开发和设计是不可分割的一个整体。






返回类别: 教程
上一教程: ASP+ 与 Java(二)
下一教程: 转业界评说:DotNet的进一步消息

您可以阅读与".NET中的特别类型成员----微软 .NET平台系列文章之三(译文/赵湘宁)"相关的教程:
· 微软.NET平台中类型使用的基本原理----微软 .NET平台系列文章之二(译文/赵湘宁)
· 在新的平台上编程 ----微软 .NET平台系列文章之一(译文/赵湘宁 )
· .NET中的特别类型成员
· 第七章 类型成员及其访问限定[《.NET框架程序设计》读书笔记]
· 微软.NET平台中类型使用的基本原理
    微笑服务 优质保证 索取样品