C#语言在面向对象设计和编程中对数据安全提出了严格的要求,其中一个重要的原则就是数据封装。根据这一原则,C#程序设计中要求开发人员对特定类的数据字段尽量不以公有方式提供给外界。因此在类内部多数字段的访问权限被限定为private或是public,而这些字段与外界的交流经常采用属性来进行。
属性使类能够以一种公开的方法获取和设置值,同时隐藏实现或验证代码。
属性是这样的成员:它们提供灵活的机制来读取、编写或计算私有字段的值。
可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。这 使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性。
属性使类能够以一种公开的方法获取和设置值,,同时隐藏实现或验证代码。
get 属性访问器用于返回属性值,而 set 访问器用于分配新值。 这些访问器可以有不同的访问级别。
get 访问器体与方法体相似。 它必须返回属性类型的值。执行 get 访问器相当于读取字段的值
get 访问器必须以 return 或 throw 语句终止,并且控制权不能离开访问器体。
value 关键字用于定义由 set 取值函数分配的值。
不实现 set 取值函数的属性是只读的。
不实现 set 取值函数的属性是只读的。
属性的定义通常由以下两部分组成:
1需要封装的专用数据成员
private int _nValue =
1;
private double _dValue =
10.101;
private char _chValue =
‘a‘;
2向外界提供访问的公共属性:
//读写属性nValue:
public int nValue
{
get
{
return _nValue;
}
set
{
_nValue =
value;
}
}
//只读属性dValue:
public double dValue
{
get
{
return _dValue;
}
}
//只写属性chValue:
public char chValue
{
set
{
_chValue =
value;
}
}
当属性的访问器中不需要其他逻辑时,自动实现的属性可使属性声明更加简洁。客户端还可以通过这些属性创建对象,例如下面的代码,编译器将创建一个私有的匿名支持字段,该字段只能通过属性的get和set访问器进行访问。
class Customer
{
// Auto-Impl Properties for trivial get and set
public double TotalPurchases {
get;
set; }
public string Name {
get;
set; }
public int CustomerID {
get;
set; }
// Constructor
public Customer(
double purchases,
string name,
int ID)
{
TotalPurchases = purchases;
Name = name;
CustomerID = ID;
}
// Methods
public string GetContactInfo() {
return "ContactInfo";}
public string GetTransactionHistory() {
return "History";}
// .. Additional methods, events, etc.
}
class Program
{
static void Main()
{
// Intialize a new object.
Customer cust1 =
new Customer (
4987.63,
"Northwind",
90108 );
//Modify a property
cust1.TotalPurchases +=
499.99;
}
}
下面讲一个如何使用自动实现的属性实现轻量类:
此示例演示如何创建一个不可变轻量类,用于仅封装一组自动实现的属性。当您必须使用引用类型语义时,请使用此种构造而不是结构。
请注意:对于自动实现的属性,需要 get 和 set 访问器。 要使该类不可变,请将 set 访问器声明为 private。 但是,声明私有 set 访问器时,不能使用对象初始值来初始化属性。
下面的示例演示两种方法来实现具有自动实现属性的不可变类。第一个类使用构造函数初始化属性,第二个类使用静态工厂方法。
class Contact
{
// Read-only properties.
public string Name {
get;
private set; }
public string Address {
get;
private set; }
// Public constructor.
public Contact(
string contactName,
string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
}
// This class is immutable. After an object is created,
// it cannot be modified from outside the class. It uses a
// static method and private constructor to initialize its properties.
public class Contact2
{
// Read-only properties.
public string Name {
get;
private set; }
public string Address {
get;
private set; }
// Private constructor.
private Contact2(
string contactName,
string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
// Public factory method.
public static Contact2
CreateContact(
string name,
string address)
{
return new Contact2(name, address);
}
}
public class Program
{
static void Main()
{
// Some simple data sources.
string[] names = {
"Terry Adams",
"Fadi Fakhouri",
"Hanying Feng",
"Cesar Garcia",
"Debra Garcia"};
string[] addresses = {
"123 Main St.",
"345 Cypress Ave.",
"678 1st Ave",
"12 108th St.",
"89 E. 42nd St."};
// Simple query to demonstrate object creation in select clause.
// Create Contact objects by using a constructor.
var query1 =
from i
in Enumerable.Range(
0,
5)
select new Contact(names[i], addresses[i]);
// List elements cannot be modified by client code.
var list = query1.ToList();
foreach (
var contact
in list)
{
Console.WriteLine(
"{0}, {1}", contact.Name, contact.Address);
}
// Create Contact2 objects by using a static factory method.
var query2 =
from i
in Enumerable.Range(
0,
5)
select Contact2.CreateContact(names[i], addresses[i]);
// Console output is identical to query1.
var list2 = query2.ToList();
// List elements cannot be modified by client code.
// CS0272:
// list2[0].Name = "Eugene Zabokritski";
// Keep the console open in debug mode.
Console.WriteLine(
"Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Terry Adams, 123 Main St.
Fadi Fakhouri, 345 Cypress Ave.
Hanying Feng, 678 1st Ave
Cesar Garcia, 12 108th St.
Debra Garcia, 89 E. 42nd St.
*/
上诉中,通过get存取器和set存取器将封装好的专有数据成员和共同属性关联起来。