第10章 属性

属性允许源代码用一个简化的语法来调用一个方法。

CLR支持两种属性:无参属性 (parameterless property) ,有参属性(parameterful property)

C#中将有参属性称为索引器(indexer)

10.1无参属性

一般用类型的字段成员来实现获取或改变类型的状态信息。

面向对象设计和编程的重要原则之一就是数据封装(data encapsulation),它意味着类型的字段永远不应该公开。强烈建议将所有的字段都设为private。

要允许获取类型状态信息,就公开一个针对该用途的方法。

封装了字段访问的方法通常称为访问器(accessor)方法(如下面的GetName,SetName)。访问器方法可以对数据的合理性进行检查,确保对象的状态不被破坏。

public sealed class Employee

{

private String m_Nmae;

private Int32 m_Age;

public String GetName()

{

return m_Nmae;

}

public void SetName(String value)

{

m_Nmae = value;

}

public Int32 GetAge()

{

return m_Age;

}

public void SetAge(Int32 value)

{

if (value < 0)

{

throw new ArgumentOutOfRangeException("value", value.ToString(), "The value must be grater than or equal to 0");

}

m_Age = value;

}

public static void Main()

{

Employee e = new Employee();

e.SetName("Jeffery Richter");

String EmployeeName = e.GetName();

e.SetAge(41);

e.SetAge(-5);

Int32 EmployeeAge = e.GetAge();

}

}

将SetXxx方法标记为protected,就可以实现只允许派生类型修改值。

以上代码中,类型的用户必须调用方法,而不能直接引用一个字段名。

编程语言和CLR还提供了一种称为属性(property)的机制,如下:

public sealed class Employee

{

private String m_Nmae;

private Int32 m_Age;

public String Name

{

get { return (m_Nmae); }

set { m_Nmae = value; }

}

public Int32 Age

{

get { return (m_Age); }

set

{

if (value < 0)

{

throw new ArgumentOutOfRangeException("value", value.ToString(), "The value must be greater than or equal to 0");

}

m_Age = value;

}

}

public static void Main()

{

Employee e = new Employee();

e.Name = "Jeffery Richter";

String EmployeeName = e.Name;

e.Age = 41;

e.Age = -5;

Int32 EmployeeAge = e.Age;

}

}

可将属性想象成智能字段(smart field),即背后有额外逻辑的字段。

每个属性都有一个名称(Name,Age)和一个类型(String,Int32不能为void)。属性不能重载。定义属性时,可以省略set方法来定义一个只读属性,或者省略get方法来定义一个只写属性。

通过属性的get和set方法来操作类型内私有的字段,是一种很常见的做法。

以前面的Employee类型为例。编译器编译这个类型时,会发现其中的Name和Age属性。由于两个属性都有get和set访问器方法,所以编译器在Employee类型中生成4个方法定义。

10.1.1自动实现的属性

如果只是为了封装一个支持字段而创建一个属性,C#还提供了更简单的语法,称为自动实现的属性(automatically Implemented Property)。

10.1.2合理定义属性

我个人不喜欢属性

10.1.3对象和集合初始化器

System.Collections命名空间包含可使用的集合类和相关的接口,提供了集合的基本功能。

IEnumerable 接口

System.Collections

该枚举数支持在非泛型集合上进行简单迭代

所有继承了IEnumerable的类,要使用foreach迭代器时,就需要使用该方法。因此也只有实现了该接口的类才可以使用foreach。


名称


说明


GetEnumerator()


返回循环访问集合的枚举数。

IList 接口

System.Collections

IList 是 ICollection 接口的子代,并且是所有(非???)泛型列表的基接口

IList继承自ICollection


名称


说明


Add(Object)


将某项添加到 IList 中。


Clear()


从 IList 中移除所有项。


Contains(Object)


确定 IList 是否包含特定值。


CopyTo(Array, Int32)


从特定的 Array 索引处开始,将 ICollection 的元素复制到一个 Array 中。(从 ICollection 继承。)


GetEnumerator()


返回循环访问集合的枚举数。(从 IEnumerable 继承。)


IndexOf(Object)


确定 IList 中特定项的索引。


Insert(Int32, Object)


将一个项插入指定索引处的 IList。


Remove(Object)


从 IList 中移除特定对象的第一个匹配项。


RemoveAt(Int32)


移除指定索引处的 IList 项。

ICollection<T> 接口

System.Collections.Generic

定义操作泛型集合的方法。

ICollection继承自IEnumerable


名称


说明


Add(T)


将某项添加到 ICollection<T> 中。


Clear()


从 ICollection<T> 中移除所有项。


Contains(T)


确定 ICollection<T> 是否包含特定值。


CopyTo(T[], Int32)


从特定的 Array 索引开始,将 ICollection<T> 的元素复制到一个 Array 中。


GetEnumerator()


返回一个循环访问集合的枚举器。(从 IEnumerable<T> 继承。)


Remove(T)


从 ICollection<T> 中移除特定对象的第一个匹配项。

ICollection主要针对静态集合;IList主要针对动态集合。

如果一个方法的返回值是IEnumerable<T> ,必须在方法后面使用.ToList()方法才能得到一个集合数据。

集合的初始化被认为是相加(Additive)操作,而非替换的操作。编译器发现Student属性的类型是List<String>,而且这个类型实现了IEnumerable<String>接口。如下:

public sealed class Classroom

{

private List<String> m_students = new List<String>();

public List<String> Students { get { return m_students; } }

public Classroom() { }

public static void Main()

{

Classroom classroom = new Classroom

{

Students = { "Chris","Jeff" }

};

//Classroom classroom = new Classroom();

//classroom.Students.Add("Chris");

//classroom.Students.Add("Jeff");

foreach (var student in classroom.Students)

Console.WriteLine(student);

}

}

10.1.4 匿名类型

10.1.5 System.Tuple类型

10.2 有参属性

重看

时间: 2024-10-22 20:55:50

第10章 属性的相关文章

第二部分 设计类型:第10章 属性

第二部分 设计类型:第10章 属性

敏捷软件开发:原则、模式与实践——第10章 LSP:Liskov替换原则

第10章 LSP:Liskov替换原则    Liskov替换原则:子类型(subtype)必须能够替换掉它们的基类型(base type). 10.1 违反LSP的情形 10.1.1 简单例子 对LSP的违反导致了OCP的违反: struct Point { double x, y;} public enum ShapeType { square, circle }; public class Shape { private ShapeType type; public Shape(Shape

SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)

SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1.2 INSERT SELECT 语句 8.1.3 INSERT EXEC 语句 8.1.4 SELECT INTO 语句 8.1.5 BULK INSERT 语句 8.1.6 标识列属性和序列对象 8.1.6.1 标识列属性 8.1.6.2 序列对象 8.2 删除数据 8.2.1 DELETE 语

&lt;&lt;Python基础教程&gt;&gt;学习笔记 | 第10章 | 充电时刻

第10章 | 充电时刻 本章主要介绍模块及其工作机制 ------ 模块 >>> import math >>> math.sin(0) 0.0 模块是程序 一个简单的模块 #hello.py print ("Hello,World!") >>> import hello Traceback (most recent call last): File "<pyshell#56>", line 1, i

第10章 表单元素(中)

第 10章表单元素[中]学习要点:1.type属性总汇2.type属性解析 本章主要探讨 HTML5中表单中 input元素的 type属性,根据不同的值来显示不同的输入框.一.type属性总汇input元素可以用来生成一个供用户输入数据的简单文本框.在默认的情况下,什么样的数据均可以输入.而通过不同的属性值,可以限制输入的内容. 属性名称 说明text 一个单行文本框,默认行为password 隐藏字符的密码框search 搜索框,在某些浏览器键入内容会出现叉标记取消submit.reset.

JavaScript高级程序设计(第三版)学习笔记8、9、10章

第8章,BOM BOM的核心对象是window,具有双重角色,既是js访问浏览器的一个接口,又是ECMAScript规定的Global对象.因此,在全局作用域中声明的函数.变量都会变成window对象的属性和方法. 例: var age = 20; function sayAge(){ alert(this.age); } alert(window.age); //20 window.sayAge(); //20 定义全局变量与在window对象上直接定义属性区别:全局变量不能通过delete操

构建之法第四次作业(6,9,10章)

通过第6章的学习,我们了解到"敏捷流程”一词,他有以下一些原则 1.尽早并持续的交付有价值的软件以满足顾客需求. 2.敏捷流程欢迎需求的变化,并利用这种变化来提高用户的竞争优势的. 3.经常发布可用的软件,发布间隔可以从几周到几个月,能短则短. 4.业务人员和开发人员在项目开发过程中应该每天共同工作. 5.以有进取心的认为项目核心,充分支持信任他们. 6.无论团队内外,面对面的交流始终是最有效的沟通方式. 7.可用的软件是衡量项目进展的主要指标. 8.敏捷流程能保持可持续的发展.领导.团队和用户

第10章 表单元素(上)

第10章表单元素[上] 学习要点:1.表单元素总汇2.表单元素解析 本章主要探讨 HTML5中表单元素,表单元素用于获取用户的输入数据.一.表单元素总汇在 HTML5的表单中,提供了各种可供用户输入的表单控件.元素名称 说明form 表示 HTML表单input 表示用来收集用户输入数据的控件textarea 表示可以输入多行文本的控件select 表示用来提供一组固定的选项option 表示提供提供一个选项optgroup 表示一组相关的 option元素button 表示可用来提交或重置的表

Javascript高级程序设计读书笔记(第10章 DOM)

第10章 DOM 10.1  节点层次 每个节点都有一个nodeType属性,用于表明节点的类型.任何节点类型必是下面中的一个: Node.Element_NODE(1); NODE.ATTRIBUTE_NODE(2); Node.TEXT_NODE(3); Node.CDATA_SECTION_NODE(4); Node.ENTITY_REFERENCE_NODE(5); Node.ENTITY_NODE(6); Node.PROCESSING_INSTRUCTION_NODE(7); Nod