上一篇结尾的时候我留下了几个问题,因为要断电了没有解决,这一篇我们继续上一篇的内容。点这里回到上一篇
问题1:
数组有多维度的,索引器也可以是多维的吗???
索引器可以是多维的,上一篇中我们定义的索引器只是一维索引器,同数组一样可以定义多维索引器。比如我们索引电影院的一个放映室的座位号,第一排第一列为1号,一排2列为2号……如下:
using system;  
using system.collections.generic;  
using system.linq;  
using system.text;  
  
namespace test1  
{//定义cinema类包含一个二维数组与一个二维访问器  
    class cinema  
    {//定义一个二维数组  
        private string[,] seat = new string[5, 5];  
    //定义一个二维访问器  
        public string this[uint a, uint b]  
        {  
            get { return seat[a, b]; }  
            set { seat[a, b] = value; }  
          
        }  
      
    }  
    class program  
    {  
        static void main(string[] args)  
        {  
            cinema movieroom = new cinema();//实例化  
            //for循环遍历写入  
            for (uint i = 1; i < 5; i++)  
            {  
                for (uint j = 1; j < 5; j++)  
                {  
                    movieroom[i, j] = "第" + i + "排 第" + j + "列";  
                }  
            }  
            //for循环遍历读出  
            for (uint i = 1; i < 5; i++)  
            {  
                for (uint j = 1; j < 5; j++)  
                {  
                    console.writeline(movieroom[i,j]+"\t"+((i-1)*4+j)+"号");               
                  
                }  
              
            }  
        }  
    }  
}
结果:
二维的索引器就是如此了,其他多维数的都以此类推,就不介绍了。
问题2:
数组能够使用foreach语句进行简单快捷的遍历,索引器也能使用foreach语句遍历么???
这个也是可以的,在解决这个问题的时候有必要弄清楚foreach的执行步骤与原理.
foreach语句:
c#中编译器会把foreach语句转化为ienumerable接口的方法和属性,比如:
string[] str = new string[] { "hc1", "hc2", "hc3", "hc4" };//定义一个数组  
            foreach (string i in str)//使用foreach遍历  
            {  
                console.writeline(i);  
            }
然而foreach语句会被解析为下面的代码段。
using system;  
using system.collections.generic;  
using system.linq;  
using system.text;  
using system.collections; //注意添加这个命名空间,否则没有ienumerator这个类  
  
namespace example  
{  
    class program  
    {  
        static void main(string[] args)  
        {  
            string[] str = new string[] {"hc1","hc2","hc3","hc4" }; //定义一个数组  
          //调用getenumerator()方法,获得数组的一个枚举  
            ienumerator per = str.getenumerator();  
          //在while循环中,只要movenext()返回true,就一直循环下去  
            while (per.movenext())  
            {  
                //用current属性访问数组中的元素  
                string p = (string)per.current;  
                console.writeline(p);  
            }  
        }  
    }  
}
结果都一样:
我们对string查看定义发现,string继承于ienumerable接口,ienumerable接口中只有一个方法getenumerator();(该方法已在string类中被实现了)该方法的作用是,返回一个循环访问集合的枚举器ienumerator,我们在转ienumerator的定义,它也是一个接口,里面只有三个方法的声明,current(获取集合中的当前元素),movenext(将枚举数推进到集合的下一个元素,成功返回true,越过结尾返回false),reset( 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前),也就是说,如果在我们自定义的类中没有实现getenumerator方法,以及current、movenext方法,就不能使用foreach语句遍历了。
foreach语句遍历自定义类:
还是上面电影院的例子,不过这次我们不用for循环输出,而是实现foreach语句遍历输出,如下:
using system;  
using system.collections.generic;  
using system.linq;  
using system.text;  
using system.collections; //添加这个很有必要  
  
namespace test1  
{//定义cinema继承ienumerable接口实现getenumerator()功能  
    class cinema:ienumerable  
    {//定义一个二维数组  
        private string[,] seat = new string[5, 5];  
      //定义座位号码  
        static public int index=-1;  
    //定义一个二维索引器  
        public string this[uint a, uint b]  
        {  
            get { return seat[a, b]; }  
            set { seat[a, b] = value; }//set访问器自带value参数  
          
        }  
        //实现getenumerator方法  
        public ienumerator getenumerator()  
        {  
            return new ienumerator(seat); //利用构造方法传入seat参数  
        }  
        //由于上面返回值的需要所以继承接口ienumerator并实现方法  
       private class ienumerator:ienumerator  
        {  
            private string[,] seats; //将传入的seat数组赋给它  
            public ienumerator(string[,] s)  
            {  
                seats = s;   
            }  
           //定义current的只读属性  
            public object current  
            {  //根据座位号推算数组的坐标也就是物理位置  
               get { return seats[1+(index/4), (index%4)+1]; }  
              
            }  
           //定义向下移动的规则  
            public bool movenext()  
            {  
                index++; //索引下一个座位号的位置  
                if (index <= 15)  
                {  
                    return true;  
                }  
                else  
                    return false;  
              
            }  
           //因为这个程序中用不到这个方法所以不实现,但是必须得写上否则会报错  
            public void reset()  
            {   
                          
            }  
          
        }  
      
    }  
    class program  
    {  
        static void main(string[] args)  
        {  
            cinema movieroom = new cinema();//实例化  
            //for循环索引写入  
            for (uint i = 1; i < 5; i++)  
            {  
                for (uint j = 1; j < 5; j++)  
                {  
                    movieroom[i, j] = "第" + i + "排 第" + j + "列";  
                }  
            }  
        //调用foreach语句遍历输出  
            foreach (string i in movieroom)  
            {  
                console.writeline(i+"\t"+(cinema.index+1)+"号");  
                  
            }  
        }  
    }  
}
结果:
结果是一样的。。。。
以上就是 c#学习日记29----二维索引器 与 foreach遍历索引器的内容。
   
 
   