Effective c# 第二版读书笔记1

1.使用属性(property),而不是可直接访问的数据成员

使用属性,可以方便地加入检查机制

如果你使用了Property,你可以非常轻松的添加一个检查机制,如下面这段代码:

    public class CustomerEx
    {
        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentException(
                    "Name cannot be blank",
                    "Name");
                name = value;
            }
            //...
        }
    }

属性可支持多线程

因为属性是用方法实现的,所以它拥有方法所拥有的一切语言特性。

比如,属性增加多线程的支持是非常方便的。你可以加强 get 和 set 访问器
(accessors)的实现来提供数据访问的同步:

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 cannot be blank",
                    "Name");
                lock (syncHandle)
                    name = value;
            }
        }
        // More Elided.
    }

同样,因为属性是用方法实现的,所以它拥有方法所拥有的一切语言特性,那么同样,属性可以被定义为virtual:

public class Customer
    {
        public virtual string Name
        {
            get;
            set;
        }
    }

注:这个好处是 需要这个属性的地方可以override,比如 在物品基类定义它的名字,可能在初始化子类时会有不一样的初始化Name的方式,但是我们访问时 又不可能为每个子类取不同的属性,这个virtual可以做到共用同一个属性,让子类负责不同的初始化。其实这个和方法是一样的道理
属性可以声明为接口,以及abstract

显而易见,你也可以把Property扩展为abstract,甚至成为interface的一部分:

public interface INameValuePair
    {
        object Name
        {
            get;
        }
        object Value
        {
            get;
            set;
        }
    }


属性可以使用泛型

你可以用泛型+接口的属性类型:

public interface INameValuePair<T>
    {
        T Name
        {
            get;
        }
        T Value
        {
            get;
            set;
        }
    }

给get 与set定义不同的访问权限
如前所述,因为属性是用方法实现的,所以它拥有方法所拥有的一切语言特性。
因为实现Property访问的方法get 与set是独立的两个方法,在C#
2.0之后,你可以给它们定义不同的访问权限,来更好的控制类成员的可见性,如下:

public class Customer
    {
        private string _name;
        public virtual string Name
        {
            get
            {
                return _name;
            }
            protected set
            {
                _name = value;
            }
        }
        //...
    }

在属性中使用索引器
想返回序列中的项,创建一个属性是非常不错的做法,如下例:

public class Customer
    {
        private int[] _theValues= new int[3] { 1,2,2};

        public int this[int index]
        {
            get
            {
                return _theValues[index];
            }
            set
            {
                _theValues[index] = value;
            }
        }
    }

    //usage:
    Customer c1 = new Customer();
    c1[1] = 666;
    var cc1 = c1[1];

在属性中使用索引器

想返回序列中的项,创建一个属性是非常不错的做法,如下例:

public class Customer
{
    private int[] _theValues= new int[3] { 1,2,2};

    public int this[int index]
    {
        get
        {
            return _theValues[index];
        }
        set
        {
            _theValues[index] = value;
        }
    }
}

//usage:
Customer c1 = new Customer();
c1[1] = 666;
var cc1 = c1[1];

索引器和单元素Property有着相同的特性,他们都是作为方法实现的,因此可以在索引器内部
实现任意的验证或者计算逻辑。索引器也可为虚的或抽象的,可以声明在接口中,
可以为只读或读写。一维且使用数字作为参数的索引器也可以参与数据绑定。
使用非整数参数的索引器可以用来定义其他的数据结构,如map和dictionary:

public class AddressEx
{
    private Dictionary<int, string> _address = new Dictionary<int, string>();
    public string this[int name]
    {
        get
        {
            return _address[name];
        }
        set
        {
            _address[name] = value;
        }
    }
}

//usage:
AddressEx a1 = new AddressEx();
a1[1] = "New York";
a1[2] = "Hong Kong";
var a11 = a1[1];

创建多维索引器

为了和多维数组保持一致,我们可以创建多维索引器,在不同的维度上使用相同或不同类型:

class ComputeValueClass
{
    public int this[int x, int y]
    {
        get { return ComputeValue(x, y); }
    }

    public int this[int x, string name]
    {
        get { return ComputeValue(x, name); }
    }

    private int ComputeValue(int x, int y)
    {
        //...
    }

    private int ComputeValue(int x, string y)
    {
        //...
    }

}

C#的所有牵引器都是用this命名,不支持对牵引器命名。
说明:以上内容大部分出自Effective C#第二版

发布了38 篇原创文章 · 获赞 14 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/sinat_23156865/article/details/70409797