在之前的随笔中,我们探讨了参数,字段,方法,我们在开始属性之前回顾一下,之前的探讨实际上串联起来就是OOP编程的思想,在接下来的文章中,我们还会讨论接口(就是行为),举个例子:我们如果要做一个学生档案,我们需要先抽象出来有那些对象实体,比如有一个学生类,里面有学生id,姓名,年龄,班级等字段。 但是这不能满足我们的需求,我们要做学生档案管理,需要知道学生的每科成绩,所以我们还需要一个成绩类,里面定义了学生的学生Id,科目,科目分数,下面是两个类的代码示例

public sealed  class Student{//学员idpublic int StudentId;//姓名public string Name;//年龄public int Age;//班级名public string classname;}public sealed class Score {//学员idpublic int StudentId;//科目public string SubjectName;//成绩public int Achievement;}

View Code

有了这两个类以后,我们就可以创建一个获取学员成绩的方法,方法的代码示例就不写了,OOP的思想最重要的在于尽可能的模块化可复用,当然为了实现这些,还有继承,多态等去实现目的,但是在继续实现过程中你可能会发现一些问题,当我们需要使用上面类型的时候,可以通过实例化直接使用,如下:

     Student stu = new Student();stu.Name = "苏云";stu.Age = 22;stu.classname = "fantasy";

View Code

但是如果我输入一个Age为-15,程序也可以通过,字段值就会被改变为-15,年龄是不存在负数的,所以这个值是不应该通过的,这就是今天的主题,属性设置,面向对象一条很重要的原则就是数据封装,意味类型字段永远不应该公开,否则很容易因为不恰当使用而破坏对象的状态,如上文我们输入的负值,当然还有一些其他原因,比如线程安全,字段为逻辑字段,其值存在于内存中的字节,通过某个算法获取得到。但是这样做就会导致一个问题,外部方法想要访问时,由于内部不公开,所以外部无法访问

CLR中提供了属性机制,我们完全可以不用担心上面的问题,我们改写一下例子一的代码示例,在实例化学生的时候,如果Age<1,就会抛出异常,可以看到是那个参数报出的异常,值是多少。

  public sealed  class Student{private int studentId;private string name;private int age;private string classname;//学员idpublic int StudentId { get { return (studentId); }set { studentId = value; } }//姓名public string Name{ get { return (name); }set { name = value; } }//年龄public int Age{get { return (age); }set{if (value<1)  throw new ArgumentOutOfRangeException("value", value.ToString(),"学生的年龄不能小于1岁");age = value;}}//班级名public string Classname { get { return (classname); }set { classname = value; } }}

View Code

属性机制使用起来很简单,每个属性都有名称和类型(类型不能为void),并且一个类中同一个字段名称只能出现一次,只需要get,set两个关键字,如果只有get那就是只读字段,只有set是只写字段。也可以在get上写计算方法获取到值,但是上述方法写起来是否觉得很麻烦?C#还支持自动属性实现,我们改写成绩类,示例代码如下,

  public sealed class Score {//学员idpublic int StudentId { get; set; }//科目public string SubjectName { get; set; }//成绩public int Achievement { get; set; }}

View Code

在C#中声明get;set但是却未提供对应方法,C#会自动声明一个私有字段,这样就可以很快定义一个属性,和写字段是一样的,但需要注意的是,属性不能作为out或ref参数传给方法,而字段可以

对象和初始化器

在之前的代码中,我们初始化学生类需要分两步,第一实例化,第二赋值,但实际上我们可以使用更简单的语法,对象初始化器初始化一个对象,只需要像下面这样一句话就可以初始化一个对象并且赋值,他做的事情和例子2是相同的。在集合中也可以使用初始化器初始化集合。

重点: 如果类没有无参的构造函数就会出现编译时错误

Student stu1 = new Student() {Name="admain",Age=15,Classname="fantasy"};

View Code

我们提到集合也可以用初始化器的方法初始化,但是集合的初始化和对象并不一样,首先要求对象或字段继承了IEnummerable<T>接口,我们示例常见的Dictionary集合如何初始化

1 Dictionary<int, string> dic = new Dictionary<int, string> {
2                 { 1,"张三"}, { 2,"李四"}
3             };
4             //等价于
5             dic.Add(1, "张三");
6             dic.Add(1, "李四");

View Code

有参属性:索引器

一个属性的get访问器方法不接收参数,则称为无参属性,用起来就和访问字段一样,除了这些与字段相似的属性,还有一种有参属性,C#里称其为索引器,下文中所有有参属性都用索引器替代,C#使用数组风格的语法来公开索引器,看下面的示例:

 1 class MyListBox
 2 {
 3     public ArrayList data = new ArrayList();
 4     public object this[int idx]  //this作索引器名称,idx是索引参数
 5     {
 6         get
 7         {
 8             if (idx > -1 && idx < data.Count)
 9             {
10                 return data[idx];
11             }
12             else
13             {
14                 return null;
15             }
16         }
17         set
18         {
19             if (idx > -1 && idx < data.Count)
20             {
21                 data[idx] = value;
22             }
23             else if (idx <= data.Count)
24             {
25                 data.Add(value);
26             }
27             else
28             {
29                 throw new ArgumentOutOfRangeException("idx", idx, "超出数组索引范围");
30             }
31         }
32     }
33 }

View Code

我们定义了一个类MyListBox,其中有一个ArrayList字段,在构造器中为其默认初始化了,在下面的代码中我们看到了如何声明一个索引器,我们返回的类型是object,索引器的返回类型一样不可以void,c#使用this[...]表达索引器,并且C#不支持静态索引器,尽管CLR支持静态有参属性,C#允许一个类型定义多个索引器,但是索引器参数集不能相同,其他一些语言中支持定义多个相同签名的索引器,因为其他一些语言中索引器可以自定命名,但是C#不允许这样做,因为C#中不允许开发人员指定索引器名称,C#为一个类型中的所有索引器都默认提供了一个叫做Item的名称,所以在C#中使用索引器只能通过不同签名来区分选择的索引器。

CLR并不区分有参属性和无参属性,对CLR来说,每个属性都只是类型中定义的一对方法,和一些元数据。下面的示例是如何调用索引器。使用起来也很简单吧

 1      //初始化MyListBox
 2             MyListBox ba = new MyListBox {
 3                 //集合初始化器初始化值
 4                 data = { "张三",20,30,40},
 5             };
 6             //调用添加方法为其添加值
 7             ba.data.Add("5");
 8             ba.data.Add(6);
 9             for (int i = 0; i < ba.data.Count; i++)
10             {
11                 //使用索引器打印出指定值,具体实现请查看类中get方法
12                 Console.WriteLine(ba.data[i]);
13             }

View Code

无参属性,初始化器,有参属性,有了这些你可以在你的方法中更好的使用字段,并且让你的数据封装更加安全,但是CLR作者本人却持有另外一种观点,作者觉得属性不如封装的方法。有兴趣的朋友可以自己翻阅CLR看看作者的观点。

转载于:https://www.cnblogs.com/Demon-Su/p/7258436.html

CLR类型设计之属性相关推荐

  1. java abc 979899_商品标题由关键词组成,关键词主要包括核心词、类目词、属性词以及长尾词四种类型。其中属性词是指...

    商品标题由关键词组成,关键词主要包括核心词.类目词.属性词以及长尾词四种类型.其中属性词是指 答:商品属性 网签备案具有创设权利的功能,能产生物权变动的效力. 答:错 下列程序执行后输出的结果是\nx ...

  2. 电商后台设计:属性管理

    编辑导语:电商平台上出售着各种各样的商品,买家通过读取这些商品的属性介绍才能了解它的信息,确定自己需不需要.适不适合.电商平台中商品数量庞大,各商品的属性又千差万别,所以设计一套可复用的属性管理功能就 ...

  3. Linq之隐式类型、自动属性、初始化器、匿名类

    目录 写在前面 系列文章 隐式类型 自动属性 初始化器 匿名类 总结 写在前面 上篇文章是本系列的小插曲,也是在项目中遇到,觉得有必要总结一下,就顺手写在了博客中,也希望能帮到一些朋友.本文将继续介绍 ...

  4. 20141230 mysql数值类型和列属性二

    20141230 mysql数值类型和列属性二 枚举字符串 枚举字符串指的是在定义之初就确定要存放的字符串有哪些,然后在数据进行存储的时候就只能存储已经定义过的字符串,只能使用任意的一个字符串.(单选 ...

  5. 如何在运行时使用SAP Commerce Cloud backoffice直接给类型增添新属性

    传统的SAP Commerce Cloud数据类型扩展工具,需要首先编辑items.xml, 增添新属性,然后重新build,花费的时间较长.而如今在Backoffice运行时可以直接给一个类型增添新 ...

  6. C语言之变量存储类型与链接属性

    文章出自个人博客https://knightyun.github.io/2018/04/28/c-storage-type,转载请申明 C语言中一个重要的东西就是弄清申明变量的类型.作用域.存储类型. ...

  7. 6 自定义控件之屏蔽控件的设计时属性

    1 屏蔽组建设计时属性                                                                    1) 重载父类的属性,然后使用Editor ...

  8. java数组子类型_在vhdl中获取数组子类型的范围属性

    您的问题是您尝试在类型上使用属性 . 但是,范围仅定义为数组(因此原型中为A) . 这意味着,即使数组类型受到约束,也需要使用实际数组 . -- Declarations -- Constrained ...

  9. 20141230 mysql数值类型和列属性一

    20141230 mysql数值类型和列属性一 回顾 数据库基础知识,关系型数据库(行/记录,列/字段,SQL) 基本SQL操作:库操作,表操作(字段)和数据操作 字符集 校对集 1. 什么是校对集? ...

最新文章

  1. 亚马逊云科技在中国区域上线机器学习新服务,打造广泛而深入的人工智能与机器学习工具集
  2. 单细胞RNA降维之UMAP
  3. Linux中的软件源详解,Ubuntu Linux 软件源详解
  4. 淮安掼蛋网页版-源码头文件总结
  5. resset-rem.css
  6. Css制作table细线表格
  7. hibernate 批量插入 Batch
  8. 《啊哈!算法》-----系列更新暂时停止
  9. 传奇源码分析-客户端(WindHorn简述和传奇文件格式分析)
  10. 计算机学报应用研究,组推荐系统及其应用研究-计算机学报.PDF
  11. mysql 解决1062报错
  12. 【jieba获取关键词】
  13. 为什么戏说php,戏说PHP的嵌套函数
  14. 【云原生】设备入云之FStudio 2.0通讯操作经验
  15. 变强——GitHub 热点速览 Vol.46
  16. 1986 年德国电气商博世公司开发出面向汽车的CAN 通信协议
  17. 计算机科学与技术1k怎么算,1K等于多少个字节?
  18. java计算机毕业设计基于安卓Android的助农商城APP-农业信息app
  19. 快递实名制 消费者信息安全有隐忧
  20. 一文说清 GIS、GPS、RS、LBS 区别与联系

热门文章

  1. SSM项目中怎样引入并使用Bootstrap
  2. 再论CMMI和敏捷的对话
  3. 组织软件测试中应当避免的几个常见现象
  4. 8、mybatis之增删改查
  5. js获取video的时长_HTML5标签之lt;videogt;二次开发(一) — 为什么(后跟重要知识点!)...
  6. lync服务器不响应或无法联系,Lync 用户无法与外部联系人通信 - Skype for Business | Microsoft Docs...
  7. Linux下Tcp保活时间默认多少,C/C++网络编程中的TCP保活
  8. php调用c语言库,使用C语言给php写扩展
  9. 神策数据加入中国大数据产业生态联盟,神策营销云及融媒解决方案获联盟认证
  10. Excel关于使用图形的妙招技法