本章讨论属性,它允许源代码用简化语法来调用方法。CLR支持两种属性:无参属性 有参属性。在C#中称有参属性索引器

无参属性

面向对象设计和编程的重要原则之一就是数据封装,意味着类型的字段永远不应该公开,否则很容易因为不恰当的使用字段而破坏对象的状态。

下面这种使用方式是不好的:

public sealed class Employee{
public String Name;
public Int32 Age
} Employee e = new Employee();
e.Name = "Jeffrey Richter";
e.Age = 45;
//下面这种方式很容易就破坏了对象的状态
e.Age = -5;

基于以上原因,强烈建议将所有字段都设为private.要允许用户或类型获取或设置状态信息就公开一个针对该用途的方法。封装了字段访问的方法通常称为访问器方法。

比如下面这样使用属性:

private sealed class Employee {
private String m_Name; // prepended 'm_' to avoid conflict
private Int32 m_Age; // prepended 'm_' to avoid conflict public String Name {
get { return (m_Name); }
set { m_Name = value; } // 'value' identifies new value
} public Int32 Age {
get { return (m_Age); }
set {
if (value <= 0) // 'value' identifies new value
throw new ArgumentOutOfRangeException("value", "must be >0");
m_Age = value;
}
}
} emp.Name = "Jeffrey Richter";
emp.Age = 45; // Updates the age
Console.WriteLine("Employee info: Name = {0}, Age = {1}", emp.Name, emp.Age); e.Age = -5; // 会抛出`ArgumentOutOfRangeException`异常
Int32 EmployeeAge = e.Age ;

注意:我相信大部分的初学者在开始之初都讲不出字段属性的区别,现在我可以稍微尝试着说下了。字段经常用来封装一些不经常修改的内容,建议将字段设为private,而属性一定要将取值get设值set想象成两个方法,虽然C#简化了这种语法,但编译器在后台仍然会在指定的属性名之前添加set_get_前缀来生成方法名,更适合用来封装那些可能发生变化的内容。可以将属性看成智能字段,可以设置只读属性只写属性

自动实现的属性

public String Name {get;set;}

声明属性而不提供get/set方法的实现,C#会自动为你声明一个私有字段。实现get/set方法。

合理定义属性

  • 属性可以只读或只写,字段访问总是可读或可写的(readonly字段在构造器中可写)。如果定义属性,最好同时位它提供getset访问方法。
  • 属性方法可抛出异常,字段不会
  • 属性不能作为outref参数传递给方法
  • 属性可能花较长时间完成,字段访问总是立即完成
  • 连续多次访问,属性方法可能每次返回不同的值,而字段每次都是相同的值

对象和集合初始化器

对象初始化语法:

Employee e = new Employee(){ Name = "Jeff" , Age = 45 };

如果想调用的本来就是一个无参构造器,C#还允许省略括号

下面演示集合初始化器,下面构造一个ClassRoom对象,并初始化Students集合

Classroom classroom = new Classroom{
Student = { "Jeff" , "Kristin" , "Aidan"}
};

使用起来还是非常方便的,编译器在后台默认调用集合的Add方法,把对象添加到集合中。

匿名类型

利用C#的匿名类型功能,可以很简洁的语法来自动声明不可变的元组类型。

 var o1 = new { Name = "Jeff", Year = 1964 };

 // Display the properties on the console:
Console.WriteLine("Name={0}, Year={1}", o1.Name, o1.Year);

匿名类型经常与LINQ联合使用

有参属性

在C#中有参属性被称为索引器。C#是用数组风格的语法来公开有参属性,换句话说索引器可以看成是C#对[]操作符的重载

下面演示一个BitArray类,它允许哦那个数组风格的语法来索引一组二进制位

internal sealed class BitArray {
//容纳了一个二进制位的私有字节数组
// Private array of bytes that hold the bits
private Byte[] m_byteArray;
private Int32 m_numBits; // Constructor that allocates the byte array and sets all bits to 0
//分配字节数组,并将所有为初始为0
public BitArray(Int32 numBits) {
// Validate arguments first.
if (numBits <= 0)
throw new ArgumentOutOfRangeException("numBits must be > 0"); // Save the number of bits.
m_numBits = numBits; // Allocate the bytes for the bit array.
m_byteArray = new Byte[(m_numBits + 7) / 8];
} // This is the indexer.
// 这是索引器
public Boolean this[Int32 bitPos] {
// 这是索引器的get方法
get {
// Validate arguments first
if ((bitPos < 0) || (bitPos >= m_numBits))
throw new ArgumentOutOfRangeException("bitPos", "bitPos must be between 0 and " + m_numBits); // Return the state of the indexed bit.
return ((m_byteArray[bitPos / 8] & (1 << (bitPos % 8))) != 0);
} // 索引器的set访问器方法
set {
if ((bitPos < 0) || (bitPos >= m_numBits))
throw new ArgumentOutOfRangeException("bitPos", "bitPos must be between 0 and " + m_numBits); if (value) {
// Turn the indexed bit on.
m_byteArray[bitPos / 8] = (Byte)
(m_byteArray[bitPos / 8] | (1 << (bitPos % 8)));
} else {
// Turn the indexed bit off.
m_byteArray[bitPos / 8] = (Byte)
(m_byteArray[bitPos / 8] & ~(1 << (bitPos % 8)));
}
}
}
} private static void BitArrayTest() {
// Allocate a BitArray that can hold 14 bits.
// 构造一个数组
BitArray ba = new BitArray(14); // Turn all the even-numbered bits on by calling the set accessor.
for (Int32 x = 0; x < 14; x++) {
//这里实际是调用的set方法,将偶数为设为true
ba[x] = (x % 2 == 0);
} // Show the state of all the bits by calling the get accessor.
for (Int32 x = 0; x < 14; x++) {
// 这里调用了get方法,显示状态。
Console.WriteLine("Bit " + x + " is " + (ba[x] ? "On" : "Off"));
}
}

C#使用this[...]作为表达索引器的语法,如上面的

public Boolean this[Int32 bitpos]

代表set时,传入一个index的索引,get时返回一个Boolean类型


总结

今天的内容还是比较有趣的, 搞懂了一直以来困惑的字段属性的区别。复习了对象初始化器、集合初始化器、匿名类型等等,最后学习了下有参属性即索引器。以前在做题的时候遇到过,现在也清楚多了。接下来到了事件了哈哈,做个小栗子一起学习下吧。

C#--属性详解的更多相关文章

  1. android:exported 属性详解

    属性详解 标签: android 2015-06-11 17:47 27940人阅读 评论(7) 收藏 举报 分类: Android(95) 项目点滴(25) 昨天在用360扫描应用漏洞时,扫描结果, ...

  2. OutputCache属性详解(一)一Duration、VaryByParam

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  3. OutputCache属性详解(二)一 Location

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  4. OutputCache属性详解(三)— VaryByHeader,VaryByCustom

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  5. OutputCache属性详解(四)— SqlDependency

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  6. WPF依赖属性详解

    WPF依赖属性详解 WPF 依赖属性 英文译为 Dependency Properties,是WPF引入的一种新类型的属性,在WPF中有着极为广泛的应用,在WPF中对于WPF Dependency P ...

  7. HTML video 视频标签全属性详解

    HTML 5 video 视频标签全属性详解   现在如果要在页面中使用video标签,需要考虑三种情况,支持Ogg Theora或者VP8(如果这玩意儿没出事的话)的(Opera.Mozilla.C ...

  8. Android组件---四大布局的属性详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4372222.html Android常见布局有下面几种: LinearL ...

  9. dede的pagelist标签的listsize数字属性详解(借鉴)

    dede的pagelist标签的listsize数字属性详解.见远seo经常用织梦搭建各种网站,有次发现列表页面的分页显示超过div的界限,也就是溢出了或者说是撑破了.后来经过研究发现是pagelis ...

  10. 轻松学习Linux之Shell文件和目录属性详解

    轻松学习Linux之Shell文件和目录属性详解 轻松学习Linux之理解Sitcky 轻松学习Linux之理解umask 轻松学习Linux之理解SUID&SGUID 本系列多媒体教程已完成 ...

随机推荐

  1. C#解决Linq OrderBy() 失效的小技巧

    前言 前几天的一个数据列表中我用了Linq GroupBy 和OrderBy. 排序在本机正常使用,发到测试后排序死活不对,很是郁闷,总以为是程序问题.于是请教了另外一个同事.有了以下的答案. 问题原 ...

  2. CSS3魔法堂:说说Multi-column Layout

    前言  是否记得<读者文摘>中那一篇篇优美感人的文章呢?那除了文章内容外,还记得那报刊.杂志独有的多栏布局吗?  当我们希望将报刊.杂志中的阅读体验迁移到网页上时,最简单直接的方式就是采用 ...

  3. Elasticsearch 全教程

    Elasticsearch 权威指南 在线阅读 国外自动指向 GITBOOK 项目 | 国内用户自动指向 阿里云 GITHUB 仓库 译者前言 译者现在的工作项目中需要用到 Elasticsearch ...

  4. Vagrant入门

    简单地说,Vagrant让我们可以通过代码的方式快速地.可重复地创建针对不同虚拟环境的虚拟机,包括Virtualbox.AWS.Docker等.它使得我们可以一次性地.自动创建多个环境相同的虚拟机,对 ...

  5. 使用canvas实现擦玻璃效果

    体验效果:http://hovertree.com/texiao/html5/25/ 效果图: 代码如下: <!DOCTYPE html> <html> <head la ...

  6. python读取文件的方法

    一. 通过readline 逐行读取: #--encoding:utf-8 with open("ha.conf","r",encoding='utf-8') ...

  7. Java--Callable与返回值future

    package com; import java.util.concurrent.*; /** * Created by yangyu on 16/11/28. */ /** * Callable a ...

  8. swift 之 纯代码创建 cell

    初学swift 但是网上只有很多swift用xib创建的cell,就算是有也不是我想要的.今天自己弄了一个不用xib纯代码写的,来上代码 博客地址: https://github.com/liguol ...

  9. 【夯实PHP基础】PHP的date函数

    本文地址 原文地址 提纲: 1. 引言 2. 代码示例 3. 参考资料 1. 引言 今天看到一段代码 $timeNew = date('n月j日', strtotime($oldTime)); 感觉有 ...

  10. AngularJS学习笔记(1) - AngularJS入门

    什么是AngularJS? AngularJS是建立在jQuery的一个轻量级版本之上的MVC框架.MVC将业务逻辑代码和视图.模型相分离.AngularJS提供的所有功能都可以通过使用JavaScr ...