`
t641339564
  • 浏览: 26408 次
  • 性别: Icon_minigender_1
  • 来自: 贵阳
社区版块
存档分类
最新评论

第4章 成员设计

阅读更多

4.1. 成员设计的一般规范

4.1.1. 成员重载

成员重载是指在同一个类型中创建两个或两个以上的成员,这些成员具有相同的名字,唯一不同的是参数的数量或参数的类型。因为只有方法、构造函数以及索引属性有参数,所以只有这些成员可以被重载。

ü 在一族对参数的数量进行重载的成员中,较长的重载应该用参数名来说明与之对应的较短的重载所使用的默认值。这最适用于布尔型参数。

例如:

public class Type

{

public MethodInfo GetMethod(string name); //ignoreCase=false

public MethodInfo GetMethod(string name, Boolean ignoreCase);

//ignoreCase而不用caseSensitive

}

 

û 避免在重载中随意地给参数命名。如果两个重载中的某个参数表示相同的输入,那么该参数的名字应该相同。

例如:

public class String

{

//correct

public int IndexOf(string value){…}

public int IndexOf(string value, int startIndex){…}

 

//incorrect

public int IndexOf(string value){…}

public int IndexOf(string str, int startIndex)

}

 

û 避免使重载成员的参数顺序不一致。在所有的重载中,同名的参数应该出现在相同的位置。

例如:

public class EventLog

{

public EventLog();

public EventLog(string logName);

public EventLog(string logName, string machineName);

public EventLog(string logName, string machineName, string source)

}

只有在一些非常特殊的情况下才能打破这条非常严格的规则。

例如:params数组参数必须是参数列表中的最后一个参数。

参数列表中包含输出参数,这些参数一般出现在参数列表的最后。

 

ü 如果需要可扩展性,要把最长的重载做成虚函数,较短的重载应该仅仅是调用较长的重载。

public class String

{

public int IndexOf(string s)

{

return IndexOf(s, 0);

}

public int IndexOf(string s, int startIndex)

{

retirm IndexOf(s, startIndex, s.Length)

}

public virtual int IndexOf(string s, int startIndex, int count)

{…}

}

 

û 不要在重载成员中使用 ref  out 修饰符。

例如:

public class SomeType

{

public void SomeType(string name){…}

public void SomeType(out string name){…}

}

 

ü 如果方法有可选的引用类型参数,要允许它为null,以表示应该使用默认值。

if (geometry == null) DrawGeometry(brush, pen);

else DrawGeometry(brush, pen, geometry);

 

ü 要优先使用成员重载,而不是定义有默认参数的成员,默认参数不符合CLS规范。

//4.0的新特性

public static void Show(string msg = "")

{

Console.WriteLine("Hello {0}",msg);

}

4.1.2. 显式地实现接口成员

如果显式实现接口成员,客户代码在调用这些接口成员时,必须把实例强制转换为接口类型。

例如:

public struct Int32:IConvertible

{

int IConvertible.ToInt32(){…}

}

 

客户代码:

int i = 0;

i.ToInt32(); //编译不通过

((IConvertible)i).ToInt32(); //编译通过

 

û 尽量避免显式实现接口成员。

 

ü 如果希望接口成员只能通过该接口来调用,可考虑显式地实现接口成员。

例如:设计ICollection<T>.IsReadOnly 的主要目的是为了让数据绑定基础设施通过ICollection<T>接口来访问。在使用该接口类型时,几乎不会直接访问该方法。因此List<T>显示实现了该接口成员。

 

ü 当需要隐藏一个成员,并增加一个名字更合适的等价成员时,可考虑显式实现接口成员。

public class FileStream:IDisposable

{

IDisposable.Diopose(){Close();}

public void Close(){…}

}

 

ü 如果希望让派生类实现功能定制,要为显式实现的接口成员提供一个功能相同的受保护的虚方法。

[Serializable]

public class List<T>:ISerializable

{

void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)

{

GetObjectData(info, context)

}

protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)

{…}

}

4.1.3. 属性和方法之间的选择

方法表示操作,属性表示数据,如果其他各方面都一样,那么应该使用属性而不是方法。

 

ü 如果成员表示类型的逻辑attribute,考虑使用属性。

例如:Button.Color是属性,因为colorbutton的一个attribute

 

ü 如果属性的值储存在内存中,而提供属性的目的仅仅是访问该值,要使用属性不要使用方法。

public Customer

{

private string name;

public Customer(string name)

{

this.name = name;

}

public string Name

{

get {return this.name;}

}

}

 

ü 要在下列情况下使用方法而不要使用属性:

Ø 操作开销较大。

Ø 操作是一个转换操作,如Object.ToString方法。

Ø 即使传入的参数不变,操作每次返回的结果都不同,如:Guid.NewGuid方法。

Ø 操作返回一个数组。

4.2. 属性的设计

ü 如果不应该让调用方改变属性的值,要创建只读属性。

 

û 不要提供只写属性,也不要让设置方法的存取范围比获取方法更广。

例如:不要把属性的设置方法设置为公有,而把获取方法设为受保护。

 

ü 要为所有属性提供合理的默认值。

 

ü 要允许用户以任何顺序来设属性的值。

 

ü 如果属性的设置方法抛出异常,要保留属性原来的值。

 

û 避免在属性的获取方法中抛出异常。

4.2.1. 索引属性的设计

索引属性通常称为索引器,它的调用语法与数组索引相似。

public class String

{

public char this[int index]

{

get {…}

}

}

string city = “suzhou”;

Console.WriteLine(city[0]);

ü 考虑通过索引器的方式让用户访问存储在内部数组中的数据。

 

û 避免有一个以上参数的索引器。

 

û 避免用System.Int32System.Int64System.StringSystem.Object、枚举或泛型参数之外的类型来做索引器的参数。

 

û 不要同时提供语义上等价的索引器和方法。

 

4.2.2. 属性改变的通知事件

有时候为用户提供通知事件来告诉他们属性值发生了改变是有用的。例如,System.Windows.Forms.Control在它的text属性值发生改变后会触发TextChange事件。

public class Control : Component

{

string text = String.Empty;

public event EventHandler<EventArgs> TextChanged;

public string Text

{

get { return text; }

set

{

if (text != value)

{

text = value;

OnTextChanged();

}

}

}

 

protected virtual void OnTextChanged()

{

EventHandler<EventArgs> handler = TextChanged;

if (handler != null)

{

handler(thisEventArgs.Empty);

}

}

}

 

ü 考虑在高层API(通常是设计器组件)的属性值被修改时触发属性改变的通知事件。

 

ü 考虑在属性值被外界修改时触发通知事件。

4.3. 构造函数的设计

有两种类型的构造函数:类型构造函数和实例构造函数。

public class Customer

{

public Customer {…} //实例构造函数

static Customer {…} //类型构造函数

}

类型构造函数时静态的,CLR会在使用该类型之前运行它。实例构造函数在类型的实例创建时运行。类型构造函数不能带任何参数,实例构造函数则可以。

 

ü 考虑提供简单的构造函数,最好是默认构造函数。

 

ü 要把构造函数的参数用作设置主要属性的便捷方法。

 

ü 如果构造函数参数用于简单的设置属性,要使用相同的名字命名构造函数参数和属性。

public class EventLog

{

public EventLog(string logName)

{

this.logName = logName;

}

public string LogName()

{

get {…}

set {…}

}

}

 

ü 要在构造函数中做最少的工作。

 

ü 要在类中显式地声明公用的默认构造函数。

 

û 避免在结构中显式地定义默认构造函数。

 

û 避免在对象的构造函数内部调用虚成员。

例如:它会在Derived的新实例创建时打印出“What’s wrong?”。

public abstract class Base

{

public Base()

{

Method();

}

 

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    ASP.NET_4高级程序设计__第4版_高清版

    第4 章 服务器控件 97 第5 章 ASP.NET 应用程序 137 第6 章 状态管理 177 第二部 分 数据访问 第7 章 ADO.NET 基础 208 第8 章 数据组件和DataSet 240 第9 章 数据绑定 265 第10 章 富数据控件 3031 第11 章 ...

    C++程序设计

    C++程序设计 第1章 绪论 第9章 运算符重载 第2章 数据类型和表达式 第10章 静态成员与友元 第3章 控制语句 第11章 继承和派生类 第4章 函数 第12章 模板 第5章 数组 第13章 多态性与虚函数 第...

    Microsoft.NET框架程序设计(修订版) 高清版

    第4章 类型基础 第5章 基元类型、引用类型与值类型 第6章 通用对象操作 第3部分 类型设计 第7章 类型成员及其访问限定 第8章 常数与字段 第9章 方法 第10章 属性 第11章 事件 第4部分 基本类型 第12章 文本处理 第13...

    PHP中文网线上培训班-PHP编程.zip

    第4章 php基础3 第5章 php基础4 第6章 mysql数据库管理 第7章 mysql数据库管理1 第8章 mysql数据库管理2 第9章 会话控制 第10章 会话控制1 第11章 细说函数 第12章 匿名函数与对象初步 第13章 对象继承与成员访问 第...

    PHP高级程序设计_模式、框架与测试

     第4章 异常  第5章 PHP 6中的新特性 第二部分 测试和文档编写  第6章 文档编写和编码规范  第7章 反射API  第8章 测试、部署和持续集成 第三部分 SPL(标准PHP库)  第9章 SPL简介  第10章 SPL迭代...

    Java高级程序设计(第二版)--第2章-异常处理.pptx

    本章任务 任务1 识别异常 任务2 处理异常 任务3 自定义百分制分数异常 任务4 使用throws关键字 Java高级程序设计(第二版)--第2章-异常处理全文共19页,当前为第4页。 2.1 什么是异常 任务1 识别异常 编程实现整数除...

    C++程序设计语言_特别版

    出版者的话 专家指导委员会 中文版序 译者序 序 第2版序 第1版序 导论 第1章 致读者 第2章 C++概览 第3章 标准库概览 第一部分 基本功能 第4章 类型和声明 第5章 指针、数组和结构 第6章 表达式和语句 第7章 函数 第...

    清华大学计算机课程之《C++程序设计》

    ◇ 第四章 流程控制语句 - 课前索引 - 第一节 if语句 - 第二节 switch语句 - 第三节 循环语句 - 第四节 break和continue语句 - 第五节 程序举例 - 本章小结 - 课后习题 ◇ 第五章 函数 - 课前索引 - 第一节...

    Visual C++2008程序设计完全自学教程

    第4章 数组和字符串 第5章 特殊类型变量——指针 第6章 函数提高程序模块化 第7章 预处理器和宏 第8章 自定义数据类型 第9章 对象和类 第10章 构造函数和类成员 第11章 类继承和友元关系  第12章 多态与...

    JAVA 面向对象程序设计第4章 抽象类和接口.pptx

    第4章 抽象类与接口;回顾;本章内容;4.1 抽象类;4.1 抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.2 ...

    C#教程 pdf

    第四章 数 据 类 型 第五章 变量和常量 第六章 类 型 转 换 第七章 表 达 式 第八章 流 程 控 制 第三部分 面向对象的C# 第九章 面向对象的程序设计 第十章 类 第十一章 方 法 第十二章 域 和 属 性 第十...

    上海交大C++面向对象

    第四章 过程化语句 第五章 函数 第六章 程序结构 第七章 数组 第八章 指针 第九章 引用 第十章 结构 第十一章 类 第十二章 构造函数与析构函数 第十三章 面向对象程序设计 第十四章 堆与拷贝...

    C#作业(第三章 类的设计和使用)

    第三章 类的设计和使用 【实验目的】 熟悉面向对象的基本概念; 进一步掌握类的成员的使用方法; 掌握对象之间通信的基本方法; 创建解决方案sy3。 1、点类 2、方法重载 3、学生管理类 4、重载 5、类的属性 6、向量...

    基于java web 的图书管理系统

    第4章 详细设计 12 4.1开发环境 12 4.2 功能模块实现 12 4.2.1登录模块 12 4.2.2 用户注册模块 13 4.2.3 图书管理模块 14 4.2.4 账户管理模块 15 4.2.5 查询模块 17 4.2.6 借阅管理模块 19 第5章 测试 20 5.1 登录...

    第1章-Java语言概述-Java面向对象程序设计教程-微课视频版-程杰-清华大学出版社.pptx

    SUN:Stanford University Network 1982年 成立 1.1 Java的诞生与发展 第1章-Java语言概述-Java面向对象程序设计教程-微课视频版-程杰-清华大学出版社全文共20页,当前为第4页。 Java产生背景 1991年4月,Sun公司的...

    Java高级程序设计实战教程第三章-Java反射机制.pptx

    Java高级程序设计实战教程第三章-Java反射机制全文共15页,当前为第4页。 3.2.2 反射机制的功能 反射机制的功能如下: 在运行时判定任意一个对象所属的类; 在运行时构造任意一个类的对象; 在运行时判定任意一个类...

    NET设计规范-.NET约定、惯用法与模式.part2

    第4章 类型设计规范 60 4.1 类型和名字空间 62 4.2 类和结构之间的选择 67 4.3 类和接口之间的选择 69 4.4 抽象类的设计 76 4.5 静态类的设计 78 4.6 接口的设计 79 4.7 结构的设计 81 4.8 枚举的...

    Java语言程序设计

    3.2.1 异常处理的意义 3.2.2 错误的分类 3.2.3 异常的处理 3.2.4 生成异常对象 3.2.5 声明自己的异常类 3.3 方法的重载 3.4 本章小结 习题第4章 类的重用第5章 接口与多态第6章 输入输出流第7章 对象群体的...

    C++面向对象程序设计教程 第4章 运算符重载

    4.1 运算符重载的概念 4.2 运算符重载方式 4.2.1 运算符重载为类的成员函数

    .NET设计规范:约定、惯用法与模式(第2版)1/5

    第4章 类型设计规范  4.1 类型和名字空间  4.2 类和结构之间的选择  4.3 类和接口之间的选择  4.4 抽象类的设计  4.5 静态类的设计  4.6 接口的设计  4.7 结构的设计  4.8 枚举的设计  4.8.1 标记枚举的...

Global site tag (gtag.js) - Google Analytics