属性、索引器知识点和练习
知识点
一、属性(Property)为我们提供了一种控制类中字段访问的简捷方法
1、什么是属性
属性(Property)是逻辑字段和物理方法的一个交集。属性的用法和字段完全相同,从逻辑上说属性就是一个字段。不过,编译器会将这个字段风格的语法自动转换为对特殊的accessor方法的调用。
1)属性的声明:
属性访问修饰符 属性类型 属性名
{
get //取值代码或称get accessor
{
...
}
set //赋值代码或称set accessor
{
...
}
}
2)使用属性
属性的好处:简言之,在访问对象成员时,既维持了封装性(即如果成员是私有时,通过对象名.成员名还是无法直接访问成员),又可以使用简洁的字段风格语法(即,虽然成员字段还保持私有,但通过对象名.属性名可以直接访问该成员字段,且书写非常简洁)。
代码中要注意:
a、成员变量字段要以小写字母开头,属性名要以大写字母开头。
b、所有的set accessor都使用value这个隐藏参数来传递要写入的数据。
c、类中和结构中的属性语法是相同的。
d、set accessor在对象初始化前是不能使用的,也就是说涉及set的相关操作必须等到对象初始化后才可以进行。而成员字段是没有此限制的。
e、不能将属性作为ref或out参数来使用。(这里不懂,存留疑问)
f、在一个属性中,最多只能包含一个get accessor和一个set accessor。属性内不能包含其他的方法、字段和属性。
g、get accessor和set accessor不能获取任何参数,赋值时,使用value变量自动传递给set accessor。
3)只读属性和只写属性
定义属性时,同时包含get accessor和set accessor的属性称为可读写属性;只包含get accessor的属性称为只读属性;只包含set accessor的属性称为只写属性。
4)属性的可访问性是指属性为private、protected、public、internal。
在声明了属性的可访问性后,还可继续对其中的set和get两种访问器设置不同的可访问性。但要注意的是:两个访问器声明时的访问修饰符不能大于或等于属性的访问修饰符,如:属性声明为private,get和set两个访问器都不能再声明为private、protected和public。同时,属性的两个访问器不允许同时声明访问修饰符(即“不能为属性或索引器的两个访问器同时指定可访问性修饰符”)如果属性的访问修饰符为public,两个访问器的访问修饰符只能设置在一个属性上,只能设置为internal或private或protected我的理解:当属性的访问修饰符确定后,如果不设置访问器的访问修饰符,即默认访问器和属性同样的访问修饰符。
二、索引器
如果将属性视为一种智能字段的话,索引器(indexer)可视为一种智能数组。使用索引器时所用的语法与使用数组时所用的语法完全相同。
什么是索引器
索引器(indexer)是类中相当特殊的一种成员。其功能类似于数组,提供类对象索引编号,并利用索引值存取类的数组成员。索引器和数组最大的不同在于索引器提供一对存取单元,让程序员能够控制经过索引存取数组成员的操作。
索引器定义:
访问修饰符 返回对象类型 关键字this [索引值的类型 索引值变量]
AccessModifier Type this [Type argindex]
{
get{...}
set{...}
}
索引器中内部分别定义了get和set存取单元,get用于取得其中元素的值,而set用于设置元素的值
索引器需注意:
1)索引器不是方法,所以参数不带圆括号,但有方括号
2)索引器总是获取单个参数,该参数是在一对方括号中提供的,用于指定要访问对象的哪一个元素。
3)和属性一样,索引器包含get和set两个访问器
4)所有索引器都使用this关键字来表示命名索引器。class和struct只允许定义一个索引器,而是总是命名为this。
5)索引器和属性相似之处:它们都使用get accessor和set accessor。区别在于:属性可以声明为static,而索引器不可。
6)索引器和数组虽然相似,但也有重要区别:a、索引器可以使用非数值下标,而数组只能用整数做下标。b、索引器可以重载,与方法相似,但数组不可。c、索引器不可以作为
ref和out参数使用,这与属性相似,而数组可以。(此处存留疑问!)
练习
属性
using System; using System.Collections.Generic; using System.Text; namespace Property { class ShowString { string str1; string str2; public string Str1 { get { return this.str1; } set { this.str1 = value; } } public string Str2 { internal get//可以声明为private、protected、internal,不能再声明成public { return this.str2; } set { this.str2 = value; } } } class Program { static void Main(string[] args) { ShowString showStr1 = new ShowString(); showStr1.Str1 = "Hello today and tomorrow!"; Console.WriteLine(showStr1.Str1); Console.ReadLine(); ShowString showStr2 = new ShowString(); showStr2.Str2 = "Test"; Console.WriteLine(showStr2.Str2); Console.ReadLine(); } } }
索引器
using System; using System.Collections.Generic; using System.Text; namespace indexer { class Int_Bits { static int bits; public static int Bits//设置为static后,下面就不能用this关键字了,因为静态不是由对象访问的,同时,get和set所访问的成员变量也必须是静态的了 { get { //return this.bits;//这是错的 return bits; } private set { bits = value; } } public Int_Bits(int initialValue) { //bits = initialValue; Int_Bits.Bits = initialValue; } public string this[string index]//索引器重载 { get { return index; } } public bool this[int index] { get { return ((bits & (1 << index))!=0);//操作符的优先级,所以括号得这样打 } set { if (value) bits |= (1 << index); else bits&=(~(1 << index)); } } } class Program { static void Main(string[] args) { int intVar = 12; Console.WriteLine("测试数据为{0}",intVar); Int_Bits intBits1 = new Int_Bits(intVar); //Int_Bits.Bits = 12; bool bit=intBits1[2]; Console.WriteLine("intBits1对象索引位置2处的比特为 {0}",bit); intBits1[3] = false; Console.WriteLine("intBits1对象索引位置3处的值改为0后的结果为 {0}",Int_Bits.Bits); Console.ReadLine(); Console.WriteLine(intBits1["hello world!"]); Console.ReadLine(); } } }