整合了下各位朋友的回答和直接的实验。总结了篇博文出来。调试到最后的时候还发现了一个VS的BUG,不知道算不算。大家一起来看下。
今天突然看到索引器这个名词。原来索引器是类里的很特殊的一种成员。它的地位和属性很像。那我就来从属性说起,毕竟属性更常见点。
private int num; //字段
public int Num//属性
{
get { return num; }
set { num = value; }
}
比如上面的代码,我们在类中定义了一个num字段。但是用了private把他封装了起来。那么外部就不能直接访问到这个字段了。但是当我们需要获得它的值或者是我们需要改变它的值的话应该怎么做呢?就是像上面这样利用一个属性来达到这样的目的。因为属性是public的。而且属性的set可以为我们保护字段设置一道防火墙。防止别人随意的设置字段的值。比如我们的num只能 是大于等于了的话,那么我们可以这样写
private int num;//字段
public int Num//属性
{
get { return num; }
set
{
if (value >= 0)//只有value大于等于了才可以被赋值给num字段
num = value;
else
num = 0;
}
}
这样就实现了属性对我们私有字段的保护了。
然后再来说说索引器。先看看索引器的格式
type this[itype argIndex]
{
get
{
.....
}
set
{
....
}
}
这里的type就是索引器的返回类型,比如Int,string等,但是必须要和你所希望操作的字段的类型一致。
看一下具体的程序
private int[] intarr = new int[5]; //定义一个长度为5的int型数组来作为类的字段
private int num; //定义个给int型的字段
public int Num //属性
{
get { return num; }
set
{
if (value >= 0)
num = value;
else
num = 0;
}
}
public int[] Intarr //intarr这个字段的属性
{
get { return intarr; }
set { intarr = value; }
}
public int this[int index] //intarr这个字段的索引器
{
get
{
return intarr[index];
}
set
{
intarr[index] = value;
}
}
然后我先用下intarr的属性看看能不能对这个数组赋值
我们发现不们不能直接这样用。我们只能传入一个数组才行。这样的话对应一个数组类型的字段来是,用属性显的很不方便。而且还有一个问题。如果我传入的不是长度为5的数组呢?它会报错嘛?如果长度是4呢?又会怎么样呢?
我们可以发现intarr的长度竟然变化了,它的长度会和传入的数组 的长度一模一样。这就不是我们希望看到的了。就好像每个人都被要求是一夫一妻的。但是一个不小心的操作造成了一夫多妻,或者可能连拥有妻子的权利都没有。所以用属性来作为一个数组型字段的接口的话不仅仅操作不方便,而且对数据的封装有很大的威胁。
然后我们来用下索引器试试。
我们可以看到,这里用索引器来操作数组型的字段变的很方便就像操作一个数组一样。那么如果我进行了次误操作比如shu1[5]=5;会发生什么呢?
这里我们程序还没有运行shu1[5]=3;这一句的时候,局部变量还都是可以看到的。但是如果我再点一次单步运行的话,程序就会直接结束,并且无视我设在下面的另一个断点。
可能有些人会觉得不可思议。觉得我乱编,但是事实就是这样,我一开始也无法接受。程序我也已经附上去了,不相信的朋友可以也去试试。我对这个现象的理解是由于我们误操作了这个字段,系统直接跳过了下面的程序。
我们可以这样验证下。
我们发现竟然label1竟然不是显示2.看来果然没有执行shu1[5]=3;下面的程序。虽然这样使用索引器的时候程序没直接报错让我们很失望,但是这可能是VS的一个BUG,系统其实是意识到了数组超长的问题的。只是没有报错。所以相比于使用属性的时候它偷偷的把我们的字段数组的长度给改变了。使用索引器还是更安全的。
总结:当被封装的字段是一个数组的时候,还是使用索引器好。操作方便而且更安全。但是VS的这个BUG还是很头疼的。
博文地址:
http://blog.sina.com.cn/s/blog_db23a6350101mjxw.html
|