日期:2014-05-17  浏览次数:20742 次

Effective C# 第二版 中文翻译之01
声明:本人原创翻译,可能翻译的不好,希望大家指正和教导。
原则一还没翻译完成,后续部分还会继续补充。
后续49个原则也会陆续翻译出来。

原则一:用属性(property)替代可访问的数据成员(Data member或field)
属性在C#语言中一直都是一等公民(译注:寓意属性在C#中有很高的地位)。从C#1.0版本以来,属性正变得越来越强大。你可以对数据的读取和赋值进行特定的、不同的约束。用属性代替数据成员,而隐式属性又能极大地减少手打输入的麻烦。如果你还在你的类中创建公有变量,如果你还在手写get和set方法,那么从现在开始,抛弃这些不好的习惯吧。属性能够在像公有接口一样提供数据成员的访问,同时,它还提供了面向对象环境中的封装。属性访问起来像是数据成员,但它却是通过方法来实现的。

类中确实有这样一些成员,它们最好还是用数据成员来表示,如:客户的名称,一个点的x、y轴位置,去年的收入等等。属性使你能够创建一个数据访问接口,它能够像访问数据成员一样进行数据访问,又同时保留的方法的所有优点。在代码中访问属性就好像是在访问公有数据成员一样。但实际上它是通过方法来实现的,所以你可以限定访问者的行为。

.NET框架假定你会用属性来替代你的公有数据成员。实际上,.NET框架的数据绑定类只支持属性,而不支持公有数据成员。在所以的数据绑定类库中都是这样的,如:WPF,WindowsForms,WebForms, Silverlight等等。数据绑定将一个对象的属性绑定到一个用户界面的控件上。数据绑定机制使用反射(reflection)来找出类型中属性的名称,如:
textBoxCity.DataBindings.Add(“Text”,address,”City”);

上面这段代码,将textBoxCity控件的Text属性绑定到address对象的City属性。如果这是一个名为City的公有数据成员,将无法进行绑定。.net框架的类库并不支持这样的用法(公有数据成员)。公有数据成员是不好的编程习惯,所以,对它们的支持没有加入到类库中。他们(类库的编写者)的决定,又给了你另一个理由去遵循这样的面向对象技术。

没错,数据绑定只应用在这样的一些类中:这些类含有一些在用户界面逻辑中显示的数据。但是这并不意味着属性只能被用在UI逻辑中。你在其它类和结构体(structure)中也应该使用属性。当你以后发现新的需求或行为时,属性将远远比数据成员更容易修改。你或许不久就会决定你的Customer类不能有空白的Name,如果你使用公有属性来定义Name,那么你只需要简单地做以下修改:

public  class  Customer
{
    private  string  Name;
    public  string  Name
    {
        get{return  Name;}
        set
        {
            if(string.IsNullOrEmpty(value))
                throw  new  ArgumentException(“Name  can  not  be  blank”,”Name”);
                Name = value;
        }
    }
}

如果你使用公有数据成员,你就必须非常小心地找出每个对Name进行赋值的代码,并对它们进行修改。那将会花费更多的时间——多得多呢!

因为属性是用方法实现的,所以为它添加多线程支持也将变得更加容易。你可以改进get和set方法来实现对数据访问的同步。如以下代码所示:

public  class  Customer
{
    private  object  syncHandle = new  object();
    
    private  string  Name;
    public  string  Name
    {
        get
        {
            Lock(syncHandle)
                return  Name;
        }
        set
        {
            if(string.IsNullOrEmpty(value))
                throw  new  ArgumentException(“Name  can  not  be  blank”,”Name”);
            lock(syncHandle)
                Name = value;
        }
    }
}

属性拥有方法的所有语言特性,它可以是虚的(虚方法virtual)。如: