伪装的方法当属性---.net 属性理解

本文介绍了在编程中如何使用属性来封装类的字段,通过get和set访问器实现对类状态信息的安全读写控制。文章详细解释了属性的实现机制及其在确保数据完整性和简化代码重构方面的优势。
属性(property)通常定义为public,表示类的对外成员。属性具有可读、可写属性,通过get和set访问器来实现其读写控制。例如上文中Client类的字段,我们可以相应地封装其为属性:
public class Client
{
    private string name;         //用户姓名
    public string Name
    {
        get { return name; }
        set
        {
            name = value == null ? String.Empty : value;
        }
    }
    private int age;                //用户年龄
    public int Age
    {
        get { return age; }
        set
        {
            if ((value > 0) && (value < 150))
            {
                age = value;
            }
            else
            {
                throw new ArgumentOutOfRangeException ("年龄信息不正确。");
            }
        }
    }
}
当我们再次以
xiaoWang.Age = 1000;
这样的方式来实现对小王的年龄进行写控制时,自然会弹出异常提示,从而达到了保护数据完整性的目的。
那么,属性的get和set访问器怎么实现对对象属性的读写控制呢?我们打开ILDASM工具查看client类反编译后的情况时,会发现如图所示的情形。
IL中不存在get和set方法,而是分别出现了get_Age、set_Age这样的方法,打开其中的任意方法分析会发现,编译器的执行逻辑是:如果发现一个属性,并且查看该属性中实现了get还是set,就对应地生成get_属性名、set_属性名两个方法。因此,我们可以说,属性的实质其实就是在编译时分别将get和set访问器实现为对外方法,从而达到控制属性的目的,而对属性的读写行为伴随的实际是一个相应方法的调用,它以一种简单的形式实现了方法     所以我们也可以定义自己的get和set访问器,例如:
public string get_Password()
{
    return password;
}
public string set_Password(string value)
{
    if (value.Length < 6)
        password = value;
}
事实上,这种实现方法正是Java语言所采用的机制,而这样的方式显然没有实现get和set访问器来得轻便,而且对属性的操作也带来多余的麻烦,所以我们推荐的还是下面的方式:
public string Password
{
    get { return password; }
    set
    {
        if (value.Length < 6)
            password = value;
    }
}
另外,get和set对属性的读写控制,是通过实现get和set的组合来实现的,如果属性为只读,则只实现get访问器即可;如果属性为可写,则实现set访问器即可。
通过对公共属性的访问来实现对类状态信息的读写控制,主要有两点好处:一是避免了对数据安全的访问限制,包含内部数据的可靠性;二是避免了类扩展或者修改带来的变量连锁反应。
至于修改变量带来的连锁反应,表现在对类的状态信息的需求信息发生变化时,如何来减少代码重构基础上,实现最小的损失和最大的补救。例如,如果对client的用户姓名由原来的简单name来标识,换成以firstName和secondName来实现,如果不是属性封装了字段而带来的隐藏内部细节的特点,那么我们在代码中就要拼命地替换原来xiaoWang.name这样的实现了。例如:
private string firstName;
private string secondName;
public string Name
{
    get { return firstName + secondName; }
}
这样带来的好处是,我们只需要更改属性定义中的实现细节,而原来程序xiaoWang.name这样的实现就不需要做任何修改即可适应新的需求。你看,这就是封装的强大力量使然。
还有一种含参属性,在C#中称为索引器(indexer),对CLR来说并没有含不含参数的区别,它只是负责将相应的访问器实现为对应的方法,不同的是含参属性中加入了对参数的处理过程罢了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值