可能你会认为只读属性就只能读取,调用者不可能改变属性值。并非所有的情况都是如此,我们看下面的示例:
2 {
3 private List<string> listOfData = new List<string> {"COM1","COM2","COM3","COM4","COM5","COM6" };
4
5 public List<string> Data
6 {
7 get { return listOfData; }
8 }
9 //其他细节省略
10 }
本来我们希望MyBusinessOjbect类的Data属性是只读的,但是现在仍然可以通过其返还的引用来改变其内部状态:
2 //访问集合
3 List<string> stuff = bo.Data;
4 //不应该这些,但是这里却允许
5 stuff.Clear();
显然,这并不是我们希望的行为,我们为类创建了严格的接口,然后让用户通过接口使用对象。我们不希望用户在我们不知道的情况下,访问或者修改对象的内部状态。我们有四种策略可以防止这种类型的内部数据结构遭受有意或无意的修改:
- 值类型
- 常量类型
- 接口
- 包装器(Wrapper)
1.值类型
当客户代码通过属性来访问值类型的成员时,实际返回的是值类型的副本,而对副本的任何修改都不会影响对象的内部状态。
2.常量类型
常量类型也是安全的(参见:Effective C# 笔记条目20)。我们可以在类型中安全地返回字符串或者其他的常量类型,客户代码不可能对它们做出任何更改,因为我们也可以保证类型内部状态的安全。
3.定义接口
通过定义接口,将客户对内部数据成员的访问权限限制在一部分功能中(参见:Effective C# 笔记条目22)。当我们创建类时,可以创建一组接口来支持类功能的子集。通过接口向外界暴露类的功能,即可尽量地避免内部数据遭到有意或无意的更改。使用IEnumerable接口向外提供List<T>的功能就是这种策略的一个应用。
4.提供包装器对象
提供一个包装器对象,仅暴露该包装器,从而限制对其中对象的访问。System.Collections.ObjectModel.ReadOnlyCollection<T>类型就是对集合的一个标准的只读封装,让其中的数据保持只读:
2 {
3 private List<string> listOfData = new List<string> {"COM1","COM2","COM3","COM4","COM5","COM6" };
4
5 public List<string> Data
6 {
7 get { return listOfData; }
8 }
9
10 public ReadOnlyCollection<string> CollectionOfData
11 {
12 get { return new ReadOnlyCollection<string>(listOfData); }
13 }
14 //其他细节省略
15 }
小节
如果将引用类型通过公有借口暴露给外界,那么对象的使用者即可绕过我们定义的方法和属性来更改对象的内部结构。这违反了我们通常的直觉,也会导致常见的错误。考虑到这一点,你应该修改类暴露出的接口。如果只是简单的返回内部数据,那么实际上就给外界赋予了访问内部成员的权限。客户代码可以调用成员中任何可用的方法。通过使用接口、包装器对象或值类型向外部提供私有数据,即可限制外界对这些数据的访问能力。
本文链接
定义
百度百科定义:超文本传输协议 (HTTP-Hypertext transfer protocol) 是分布式,协作式,超媒体系统应用之间的通信协议。是万维网(world wide web)交换信息的基础。它允许将超文本标记语言 (HTML) 文档从 Web 服务器传送到 Web 浏览器。HTML 是一种用于创建文档的标记语言,这些文档包含到相关信息的链接。您可以单击一个链接来访问其它文档、图像或多媒体对象,并获得关于链接项的附加信息。
OSI层的位置
HTTP工作在TCP/IP协议体系中的TCP协议上。客户机和服务器必须都支持 HTTP,才能在万维网上发送和接收 HTML 文档并进行交互。
特点
本文链接
本例实现通过RadioButton对DataList控件进行单选。你可以参考下面演示。
准备好一个星座对象,并定义好一个泛型List来存储每一个星座名称。
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for Constellation
/// </summary>
namespace Insus.NET
{
public class Constellation
{
private int _ID;
private string _Name;
public int ID
{
get { return _ID; }
set { _ID = value; }
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public Constellation()
{
//
// TODO: Add constructor logic here
//
}
public Constellation(int id, string name)
{
this._ID = id;
this._Name = name;
}
public List<Constellation> GetConstellation()
{
List<Constellation> constellation = new List<Constellation>();
Constellation c = new Constellation(1, " 白羊座");
constellation.Add(c);
c = new Constellation(2, "金牛座");
constellation.Add(c);
c = new Constellation(3, "双子座");
constellation.Add(c);
c = new Constellation(4, "巨蟹座");
constellation.Add(c);
c = new Constellation(5, "狮子座");
constellation.Add(c);
c = new Constellation(6, "处女座");
constellation.Add(c);
c = new Constellation(7, "天秤座 ");
constellation.Add(c);
c = new Constellation(8, "天蝎座");
constellation.Add(c);
c = new Constellation(9, "射手座");
constellation.Add(c);
c = new Constellation(10, "摩羯座");
constellation.Add(c);
c = new Constellation(11, "水瓶座");
constellation.Add(c);
c = new Constellation(12, "双鱼座");
constellation.Add(c);
return constellation;
}
}
}
在.aspx拉一个DataList控件,把RadioButton置于DataList的ItemTemplate模版内。
<ItemStyle BorderWidth="1" />
<ItemTemplate>
<table>
<tr>
<td>
<asp:RadioButton ID="RadioButtonSelect"