属性和索引器

属性是字段向方法的过渡
 1public class Person
 2    {
 3
 4        public int age;//直接公开字段,无法控制用户输入非法的值
 5
 6
 7        //Java模式的对Age控制方式,需要两个方法,Get和Set。麻烦麻烦阿!
 8        public int GetAge()
 9        {
10            return Age;
11        }

12
13        public void SetAge(int personAge)
14        {
15            if (personAge < 18)
16            {
17                personAge = 18;
18            }

19            if (personAge>81)
20            {
21                personAge = 81;
22            }

23            age = personAge;
24        }

25
26        //C#模式的Age控制方式,Set和Get是属性的两个访问器,管理方便
27        public int Age
28        {
29            set
30            {
31                if (value < 18)
32                {
33                    value = 18;
34                }

35                if (value > 81)
36                {
37                    value = 81;
38                }

39                age = value;
40            }

41            get
42            {
43                return age;
44            }

45        
46        }

47    
48    }

 现在我们来看一个应用,描述部门和员工的一对多的关系。先看一个错误的设计:

 1    public class Space
 2    {
 3
 4        public static void Main(string[] args)
 5        {
 6            Department dep = new Department();
 7            //错误一,Staffs所存储的值类型无法被控制。Staffs又可以放字符串,又可以放对象 数据无法统一。
 8            dep.Staffs.Add("leo");      //放字符串
 9            dep.Staffs.Add(new Staff("King"));      //放对象
10
11            //错误二,一旦Department对Staffs的设计改变(比如用数组描述),遍历代码就要改变
                   //遍历1:类Department将Staffs描述为字符串
12            for (int i = 0; i <= dep.Staffs.Count - 1; i++)
13            {
14                System.Console.WriteLine(dep.Staffs[i]);
15            }

16                             
                  //遍历2:类Department将Staffs描述为数组
17            for (int i = 0; i <= dep.Staffs.Length - 1; i++)
18            {
19                System.Console.WriteLine(dep.Staffs[i]);
20            }

21
                  //造成用户必须根据Staffs数据描述的方式不同而编写不同的代码的原因为类Department设计不合理。
22        }

23    }

24
25    public class Department
26    {
27        //这是一个错误的设计,向用户暴露了Staffs的数据结构
28        public System.Collections.ArrayList Staffs = new System.Collections.ArrayList();
29    }

30
31    public class Department
32    {
33        //这是一个错误的设计,向用户暴露了Staffs的数据结构
34        public Staff[] Staffs = new Staff[] new Staff("leo"), new Staff("King") };
35    }

36
37    public class Staff
38    {
39        public Staff(string name)
40        {
41            Name = name;
42        }

43
44        public string Name;
45    }


好的设计方法是向用户关闭数据结构的细节

 1    public class Space
 2    {
 3
 4        public static void Main(string[] args)
 5        {
 6            Department dep = new Department();
 7            //无论将来Staffs的数据结构有什么变化,调用的代码不会有变化
 8            dep.AddStaff(new Staff("leo"));
 9            dep.AddStaff(new Staff("King"));
10            for (int i = 0; i <= dep.StaffsCount - 1;i++ )
11            {
12                System.Console.WriteLine(dep.GetStaffFromIndex(i).Name);
13            }

14        }

15    }

16
17    public class Department
18    {
19        //这是正确的设计
20        private System.Collections.ArrayList Staffs = new System.Collections.ArrayList();   //private隐藏了Staffs的数据结构
21
22        public int StaffsCount                //统一遍历代码
23        {
24            get
25            {
26                return Staffs.Count;
27            }

28        }

29
30        public int AddStaff(Staff staff)                //统一Staffs的数据结构
31        {
32            return this.Staffs.Add(staff);
33        }

34
35        public void Remove(Staff staff)
36        {
37            this.Staffs.Remove(staff);                                                      
38        }

39
40        public Staff GetStaffFromIndex(int index)
41        {
42            return (Staff)this.Staffs[index];
43        }

44
45    }

46
47    public class Staff
48    {
49        public Staff(string name)
50        {
51            Name = name;
52        }

53
54        public string Name;
55    }

如果我们引入索引器,那代码能更合理

 1    public class Space
 2    {
 3
 4        public static void Main(string[] args)
 5        {
 6            Department dep = new Department();
 7            //无论将来Staffs的数据结构有什么变化,调用的代码不会有变化
 8            dep.AddStaff(new Staff("leo"));
 9            dep.AddStaff(new Staff("King"));
10            for (int i = 0; i <= dep.StaffsCount - 1;i++ )
11            {
12                System.Console.WriteLine(dep[i].Name);          //注意下标    
13            }

14        }

15    }

16
17    public class Department
18    {
19        //这是正确的设计
20        private System.Collections.ArrayList Staffs = new System.Collections.ArrayList();
21
22        public int StaffsCount
23        {
24            get
25            {
26                return Staffs.Count;
27            }

28        }

29
30        public int AddStaff(Staff staff)
31        {
32            return this.Staffs.Add(staff);
33        }

34
35        public void Remove(Staff staff)
36        {
37            this.Staffs.Remove(staff);                                                      
38        }

39
40        public Staff this[int index]
41        {
42            set
43            {
44                Staff[index] = value;
45            }

46            get
47            {
48                return (Staff)Staff[index];
49            }

50        }

51
52    }


注意代码的第40的变化,不过在一个类中,只能有一个this[int index]。
注意使用了第40行的索引器,第12行可以象数组下标一样用啦。

不过,这样的设计还不完善,请看下篇,初见继承威力。

原文地址:https://www.cnblogs.com/shyleoking/p/648739.html