(教学思路 C#之类二)类成员:属性

简介:
属性

    上节课我把属性形容成是一个进入房间的窗户或通道,关闭着的房间就是封装好的类,那么属性用代码要如何解释呢?其实这个问题,在我刚学习属性时也是很不理解,如果需要对字段的值进行判断,就写我上面的两段代码(17-38行)不就可以了吗?但是随着我们学习的不断深入,属性是必须掌握的一个知识点,现在同学们只需要会定义属性,同时会访问属性就可以了,日后深入学习(如windowsform)时,我们就理解属性的用法和好处了。在我们这个例子中属性机制就要做到如同守门员一样,限制住非海、陆、空的三种军种,下面把按照刚才军种的例子我来单独写一段代码,同时使用属性,在看代码前,我们先来看一下如何定义一个属性,它的基本语法是:  
      ptype   pname
{
    get{//取字段数据程序代码}
    set{//设定字段数据程序代码}
}
     其中ptype为属性类型,pname为属性的名称,set和get的相关程序代码可以让我们设置私有字段的访问控制,set会接受外部传入的值,并自动地以名称为value的变量存储这个值。因此在set程序区块,你必须将 value这个变量指定给对应的字段,这相对地也提供了一个缓冲的空间,让我们能够在区块内编写适当的程序代码,避免不适当的字段值设定操作,比如我上一篇的例子“男性”不是军种的一种,我们在调用军种这个字段时,赋值除了海陆空三种值后,要出现报错的提示,只有对特殊字段做出限制时,你编写的程序才更加合理。在get程序区快中,必须使用 return关键字,将其对应的字段值返回给引用此属性的程序代码,同样我们也可以将运算程序代码写在这个区块中,以判断是否返回指定的字段值。比如:在网站中每个人注册的都是真实的年龄中定义的,我们可以做一个假象,让所以人的年龄在显示的时候都比实际年龄大3岁,这就通过get区块中return出虚假的年龄。下面我们来看一段声明属性的代码:
定义年龄属性
 1  class Ren 
 2        { 
 3                 //先定义一个私有变量实际年龄age 
 4                 int age = 10; 
 5 
 6                 //再定义一个属性, 
 7                 public  int Age 
 8                { 
 9                         //输出时的年龄比实际年龄age大三岁,即输出的是10+3岁 
10                        get {  return age + 3; } 
11                         //给年龄赋值时,先判断年龄的范围 
12                        set    
13                        { 
14                                 //如果年龄小于1岁或是大于120岁时,不允许赋值,提示错误。 
15                                 if (value < 1 || value > 120) 
16                                        Console.WriteLine( "您输入的年龄有误"); 
17                                  //如果年龄符合范围,允许赋值,赋完值后的age即是value你赋的值。 
18                                 else 
19                                        age = value; 
20                         
21                        } 
22                }
      上面的实例就是一个属性的构造过程和方法,我在get和set访问器中都加入了条件,并且是我手动书写的,VS给我们提供了一个自动封装字段的方法,下面我们来按照我说的步骤来试一下,在类中定义一个字段 string a="我是A"; 接着把鼠标停放到a处,点击右键“重构”--“封装字段”,VS会自动的封装a字段,并且取名为A,你也可以更改属性的名字,点击确定,a字段的A属性就封装好了,封装后的代码为:
       string a = "我是A";
        public string A
        {
            get { return a; }
            set { a = value; }
        }
      通常我们都习惯叫get访问器和set访问器,如果我们想得到类中的属性值时,用到的是get访问器return返回出值,如果我们想给属性赋值的时候,就会用到set访问器, 属性有4种形式:分别是可读可写属性,既有get也有set访问器;如果只有get访问器,这个属性是只读的,无法赋值;如果只有set访问器,这个属性就只能被赋值,不能读取,以后我们要学习界面设计时,所有的控件都有很多的属性,这些属性就都是只写的,并且有一定的赋值要求,比如在网页上画一个表格,我们设置表格的边框颜色,就使用到边框颜色的属性,如果我们赋的颜色值不符合规范,就会出现错误提示;还有一种属性是加入了static关键字的静态属性,静态属性只能封装静态数据,比如:string static a = "我是静态A";
        public  static string A
        {
            get { return a; }
            set { a = value; }
        }
       下面我们把上面的例子继续深化,声明一个对象boby,我们来具体看一下如果利用属性的读写功能:
属性的用法
 1      class Ren 
 2        { 
 3                 //先定义一个私有变量实际年龄age 
 4                 int age = 10; 
 5 
 6                 //再定义一个属性, 
 7                 public  int Age 
 8                { 
 9                         //输出时的年龄比实际年龄age大三岁,即输出的是10+3岁 
10                        get {  return age + 3; } 
11                         //给年龄赋值时,先判断年龄的范围 
12                        set    
13                        { 
14                                 //如果年龄小于1岁或是大于120岁时,不允许赋值,提示错误。 
15                                 if (value < 1 || value > 120) 
16                                        Console.WriteLine( "您输入的年龄有误"); 
17                                  //如果年龄符合范围,允许赋值,赋完值后的age即是value你赋的值。 
18                                 else 
19                                        age = value; 
20                         
21                        } 
22                } 
23                 //定义一个得到真实年龄的方法 
24                 public  void realage() 
25                { 
26                        Console.WriteLine( "真实年龄为" + age +  "岁"); 
27                } 
28        } 
29         class Program 
30        { 
31 
32                 static  void Main( string[] args) 
33                { 
34                         //实例化一个人Ren类aboy孩子对象 
35                        Ren aboy =  new Ren(); 
36                        
37                         //此时打印出的是,未通过属性直接用到的age初值,也就是真实年龄。 
38                        aboy.realage(); 
39                        Console.WriteLine(); 
40 
41                         //现在我们直接取得孩子的年龄,因为age是私有变量,我们必须通过属性Age得到,值为虚假的大三岁的年龄 
42                        Console.WriteLine( "通过属性得到的年龄为:"+aboy .Age); 
43                        Console.WriteLine(); 
44 
45                         //现在我们给孩子的年龄赋一个0岁的值,因为age是私有变量,同样赋值也是通过属性Age, 
46                         //此时由于年龄范围的限制,是会报错的。 
47                        aboy.Age = 0; 
48 
49                         //我们再给孩子的年龄赋一个12岁,因为age是私有变量,同样赋值也是通过属性Age 
50                        aboy.Age = 12; 
51                        Console.WriteLine(); 
52 
53                         //此时因为年龄的范围合法,原来的age=10,便被替换成了12。 
54                         //我们再来打印孩子的真实年龄 
55                        aboy.realage(); 
56                        Console.WriteLine(); 
57                         //我们再来打印一下age改为12后的虚假年龄Age 
58                        Console.WriteLine( "通过属性得到的年龄为:" + aboy.Age); 
59                        Console.WriteLine(); 
60 
61                } 
62        }
 我们来看一下运行的结果:
 
真实年龄为10岁
通过属性得到的年龄为:13
您输入的年龄有误
真实年龄为12岁
通过属性得到的年龄为:15
   通过这个实例相信大家已经了解了属性的用法,下面我们把我上节课有关军种的实例做一下改动,同学们再来体会一下属性的用法:
 
 
优化军种属性
 1class Armyman 
 2        { 
 3                 //public string Armytype = ""; 
 4                 //public void ArmyFunction() 
 5                 //{ 
 6                 //        switch (Armytype) 
 7                 //        { 
 8                 //                case "陆军": 
 9                 //                        Console.WriteLine("现代陆军都是大规模的机械化部队,拥有大量的重装备和后勤补给。"); 
10                 //                        break; 
11                 //                case "海军": 
12                 //                        Console.WriteLine("杜鲁门曾说过:海军到哪里,国家的权利就到哪里 ."); 
13                 //                        break; 
14                 //                case "空军": 
15                 //                        Console.WriteLine("战略空军将使战争形态向可控战争转变。"); 
16                 //                        break; 
17                 //                default: 
18                 //                        Console.WriteLine("{0}不是兵种,请输入现代战争中的三大兵种!海军、陆军、空军", Armytype); 
19                 //                        break; 
20                 //        } 
21                 //} 
22                 //下面的代码实现了和上面一下的功能,先定义一个私有的字段Armytype,再定义一个属性 
23                         string Armytype = ""; 
24                          public  string Armytype1 
25                        { 
26                                get { 
27                                         return Armytype; 
28 
29                                } 
30                                set 
31                                { 
32                                         switch (value) 
33                                        { 
34                                                 case  "陆军"
35                                                        Console.WriteLine( "现代陆军都是大规模的机械化部队,拥有大量的重装备和后勤补给。"); 
36                                                        Armytype = value; 
37                                                         break
38                                                 case  "海军"
39                                                        Console.WriteLine( "杜鲁门曾说过:海军到哪里,国家的权利就到哪里 ."); 
40                                                        Armytype = value; 
41                                                         break
42                                                 case  "空军"
43                                                        Console.WriteLine( "战略空军将使战争形态向可控战争转变。"); 
44                                                        Armytype = value; 
45                                                         break
46                                                 default
47                                                        Console.WriteLine( "{0}不是兵种,请输入现代战争中的三大兵种!海军、陆军、空军", Armytype); 
48                                                         break
49                                        } 
50                                } 
51                        } 
52 
53                } 
54         class Program 
55        { 
56 
57                 static  void Main( string[] args) 
58                { 
59                         //我们来创建一个军人类Armyman 的实例对象ASoldiers(士兵) 
60                        Armyman ASoldiers =  new Armyman(); 
61 
62                         //当赋值除海军、陆军、空军时,出现错误提示 
63                        ASoldiers.Armytype1 =  "男性"
64                         //因为有属性赋值时的判断,所以此时属性Armytype1还是原来Armytype字段的初值:空 
65                        Console.WriteLine( "赋值后的军种为:" + ASoldiers.Armytype1); 
66                        Console.WriteLine(); 
67 
68                         //当正常赋值时,得到正确的结果。 
69                        ASoldiers.Armytype1 =  "空军"
70                        Console.WriteLine(); 
71                         //因为有属性赋值时的判断,所以此时属性Armytype1是已经赋的“空军” 
72                        Console.WriteLine( "赋值后的军种为:" + ASoldiers.Armytype1); 
73 
74                         //ASoldiers.Armytype = "男性"; 
75                         //ASoldiers.ArmyFunction(); 
76                         //Console.WriteLine(ASoldiers.Armytype); 
77 
78                } 
79        } 
80                }
 
运行结果为
 
不是兵种,请输入现代战争中的三大兵种!海军、陆军、空军
赋值后的军种为:
战略空军将使战争形态向可控战争转变。
赋值后的军种为:空军
请按任意键继续. . .
对比我上节课用的普通方法即(被我注释掉的)代码如下:
  
对比代码
 1class Armyman 
 2        { 
 3                 public  string Armytype = ""; 
 4                 public  void ArmyFunction() 
 5                { 
 6                         switch (Armytype) 
 7                        { 
 8                                 case  "陆军"
 9                                        Console.WriteLine( "现代陆军都是大规模的机械化部队,拥有大量的重装备和后勤补给。"); 
10                                         break
11                                 case  "海军"
12                                        Console.WriteLine( "杜鲁门曾说过:海军到哪里,国家的权利就到哪里 ."); 
13                                         break
14                                 case  "空军"
15                                        Console.WriteLine( "战略空军将使战争形态向可控战争转变。"); 
16                                         break
17                                 default
18                                        Console.WriteLine( "{0}不是兵种,请输入现代战争中的三大兵种!海军、陆军、空军", Armytype); 
19                                         break
20                        } 
21                } 
22                 //下面的代码实现了和上面一下的功能,先定义一个私有的字段Armytype,再定义一个属性 
23                         //string Armytype = ""; 
24                         // public string Armytype1 
25                         //{ 
26                         //        get { 
27                         //                return Armytype; 
28 
29                         //        } 
30                         //        set 
31                         //        { 
32                         //                switch (value) 
33                         //                { 
34                         //                        case "陆军": 
35                         //                                Console.WriteLine("现代陆军都是大规模的机械化部队,拥有大量的重装备和后勤补给。"); 
36                         //                                Armytype = value; 
37                         //                                break; 
38                         //                        case "海军": 
39                         //                                Console.WriteLine("杜鲁门曾说过:海军到哪里,国家的权利就到哪里 ."); 
40                         //                                Armytype = value; 
41                         //                                break; 
42                         //                        case "空军": 
43                         //                                Console.WriteLine("战略空军将使战争形态向可控战争转变。"); 
44                         //                                Armytype = value; 
45                         //                                break; 
46                         //                        default: 
47                         //                                Console.WriteLine("{0}不是兵种,请输入现代战争中的三大兵种!海军、陆军、空军", Armytype); 
48                         //                                break; 
49                         //                } 
50                         //        } 
51                         //} 
52 
53                } 
54         class Program 
55        { 
56 
57                 static  void Main( string[] args) 
58                { 
59                         //我们来创建一个军人类Armyman 的实例对象ASoldiers(士兵) 
60                        Armyman ASoldiers =  new Armyman(); 
61 
62                        /** /////当赋值除海军、陆军、空军时,出现错误提示 
63                         //ASoldiers.Armytype1 = "男性"; 
64                        /** /////因为有属性赋值时的判断,所以此时属性Armytype1还是原来Armytype字段的初值:空 
65                         //Console.WriteLine("赋值后的军种为:" + ASoldiers.Armytype1); 
66                         //Console.WriteLine(); 
67 
68                        /** /////当正常赋值时,得到正确的结果。 
69                         //ASoldiers.Armytype1 = "空军"; 
70                         //Console.WriteLine(); 
71                        /** /////因为有属性赋值时的判断,所以此时属性Armytype1是已经赋的“空军” 
72                         //Console.WriteLine("赋值后的军种为:" + ASoldiers.Armytype1); 
73 
74 
75                         //给字段Armytype赋值为“男性” 
76                        ASoldiers.Armytype =  "男性"
77                         //可以通过这个方法告知男性不符合赋值规则,输出提示 
78                        ASoldiers.ArmyFunction(); 
79                         //但此时,“男性”这个值已经赋给了Armytype字段,这是错误的做法。 
80                        Console.WriteLine(ASoldiers.Armytype); 
81 
82                } 
83        } 
84                }
运行结果如下:
男性不是兵种,请输入现代战争中的三大兵种!海军、陆军、空军
男性
请按任意键继续. . .
 
     从结果来看,很明显,如果用上面的例子,男性这个军种如果不采用属性,而是用被我注释掉的方法(第3行)一定会被赋值给Armytype字段的,而使用了属性时,“男性”因为进入了default代码快如46-48行,我们没有加入Armytype=value;这句代码,使得无法对字段Armytype赋值,这时代码第65行,Armytype1的值仍然为空,而不是“男性”,属性的优点就体现在这,所以我在前面的课程中曾说属性是保护字段的。
        本节课我们就讲到这,下节课我们来学习方法的参数类型.
本文转自叶子文文博客51CTO博客,原文链接http://blog.51cto.com/leafwf/185724如需转载请自行联系原作者

叶子文文
相关文章
|
1月前
|
开发框架 .NET C#
C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式
【10月更文挑战第9天】在 C#/.NET Core 中,有多种方法可以删除字符串的最后一个字符,包括使用 `Substring` 方法、`Remove` 方法、`ToCharArray` 与 `Array.Copy`、`StringBuilder`、正则表达式、循环遍历字符数组以及使用 LINQ 的 `SkipLast` 方法。
|
2月前
|
存储 C# 索引
C# 一分钟浅谈:数组与集合类的基本操作
【9月更文挑战第1天】本文详细介绍了C#中数组和集合类的基本操作,包括创建、访问、遍历及常见问题的解决方法。数组适用于固定长度的数据存储,而集合类如`List<T>`则提供了动态扩展的能力。文章通过示例代码展示了如何处理索引越界、数组长度不可变及集合容量不足等问题,并提供了解决方案。掌握这些基础知识可使程序更加高效和清晰。
75 2
|
3月前
|
C#
一文搞懂C#中类成员的可访问性
一文搞懂C#中类成员的可访问性
51 5
|
2月前
|
安全 C# 索引
C#一分钟浅谈:属性与索引器的定义
本文深入浅出地介绍了C#编程中的属性和索引器。属性让字段更安全,通过访问器方法在读写时执行额外操作,如验证数据有效性;索引器则赋予类数组般的访问方式,支持基于索引的数据访问模式。文章通过示例代码展示了如何定义及使用这两种特性,并提供了常见问题及其解决方案,帮助读者写出更健壮、易维护的代码。希望读者能从中学习到如何有效利用属性和索引器增强C#类的功能性。
79 12
|
29天前
|
Java 程序员 C#
【类的应用】C#应用之派生类构造方法给基类构造方法传参赋值
【类的应用】C#应用之派生类构造方法给基类构造方法传参赋值
10 0
|
2月前
|
C# 数据安全/隐私保护
C# 一分钟浅谈:类与对象的概念理解
【9月更文挑战第2天】本文从零开始详细介绍了C#中的类与对象概念。类作为一种自定义数据类型,定义了对象的属性和方法;对象则是类的实例,拥有独立的状态。通过具体代码示例,如定义 `Person` 类及其实例化过程,帮助读者更好地理解和应用这两个核心概念。此外,还总结了常见的问题及解决方法,为编写高质量的面向对象程序奠定基础。
25 2
|
3月前
|
Java C# 索引
C# 面向对象编程(一)——类
C# 面向对象编程(一)——类
33 0
|
3月前
|
开发框架 .NET 编译器
C# 中的记录(record)类型和类(class)类型对比总结
C# 中的记录(record)类型和类(class)类型对比总结
|
2天前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
13 3
|
23天前
|
安全 C# 数据安全/隐私保护
实现C#编程文件夹加锁保护
【10月更文挑战第16天】本文介绍了两种用 C# 实现文件夹保护的方法:一是通过设置文件系统权限,阻止普通用户访问;二是使用加密技术,对文件夹中的文件进行加密,防止未授权访问。提供了示例代码和使用方法,适用于不同安全需求的场景。