C# 中常用的索引器

使用 C# 中的索引器和 JavaScript 中访问对象的习性是很一般。

事先通晓过索引器,当时还把索引器和总体性给记混了,
以为索引器就是性质,上边写下索引器和特性的分化,以及怎么利用索引器

先表明某些,那里的索引器和数据库中的索引不等同,纵然都是找元素。

索引器和总体性的不相同:

  1. 特性和索引器都是函数,不过表现格局不一样等;(属性和索引器在代码的表现形式上和函数不平等,但其本质都是函数,须求经过
    ILDASM 来查看,或者应用反射)
  2. 索引器可以被重载,而属性没有重载这一说法;(索引器的重载即方括号中的类型不一样)
  3. 索引器不可能声称为static,而属性可以;(索引器之所以不能宣称为
    static,因为其自身率领 this 关键字,须要被对象调用)

再有少数就是索引很像数组,它同意一个目标足以像数组一样被中括号 []
索引,可是和数组有分别,具体有:

  1. 数组的角标只好是数字,而索引器的角标能够是数字也可以是援引类型;
  2. 数组是一个引用类型的变量,而索引器是一个函数;

     
我在代码中很少自己定义索引器,可是本人却不时在用它,那是因为系统自定义了许多索引器,比如
ADO.NET 中对于 DataTable 和 DataRow
等类的各类遍历,查找,很多地点就是用的索引器,比如上边这篇博客中的代码就利用了重重系统自定义的索引器:

DataTable的AcceptChanges()方法和DataRow的RowState属性
(其中索引器的施用都以及声明,)

 

那大家什么样自定索引器?
回到那篇博客第一句话,我曾经把索引器和特性弄混过,那就印证她们很像,看下代码看是否很像:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Dynamic;
//这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段
namespace Demo1
{
    public class IndexerClass
    {
        private string[] name = new string[2];
        //索引器必须以this关键字定义,其实这个this就是类实例化之后的对象
        public string this[int index]
        {
            //实现索引器的get方法
            get
            {
                if (index >= 0 && index < 2)
                {
                    return name[index];
                }
                return null;
            }
            //实现索引器的set方法
            set
            {
                if (index >= 0 && index < 2)
                {
                    name[index] = value;
                }
            }
        }
    }

class Program
{
static void Main(string[] args)
{
//索引器的利用
IndexerClass Indexer = new IndexerClass();
//“=”号右边对索引器赋值,其实就是调用其set方法
Indexer[0] = “张三”;
Indexer[1] = “李四”;
//输出索引器的值,其实就是调用其get方法
Console.WriteLine(Indexer[0]);
Console.WriteLine(Indexer[1]);
}
}
}

      乍一眼看上去,感觉和性质大约了,
然则周详一看,索引器没有称谓,有对方括号,而且多了 this
关键字,看到此间的 this 的例外用法又让自身想开了扩展方法中的
this的分外规地点。

     
上面再讲索引和性质的不一致时,说到了索引其实也是函数,评释索引器是函数,我在上边的的代码中投入了一个平凡方法
Add,

public class IndexerClass
    {
        public string[] strArr = new string[2];
        //一个属性
        public int Age { get; set; }
        //一个方法
        public int Add(int a,int b)
        {
            return a + b;
        }
        //一个索引器
        public string this[int index]
        {
            get
            {
                if (index < 2 && index >= 0)
                    return strArr[index];
                return null;
            }
            set
            {
                if (index >= 0 && index < 2)
                {
                    strArr[index] = value;
                }
            }
        }
    }

     大家将次第重新编译一下,然后利用 ILDASM 工具查看下编译出来的 .exe
文件,如下图:

C# 1

      从中大家得以观望一个 Add
的不二法门,C# 2那些小图标代表着法子,一共有
6 个艺术,其中 .ctor 暂时不管,Add 方法是我们团结一心写的,

get_Age : int32(),那几个办法是性质 age 的读方法,对应的还有个写方法;

还剩余五个就是索引器生成的法子了,get_Item:string(int32) 和 set_Item
: void(int32) ;

再有那样的图标C# 3,那些图标是象征着字段,上边的多少个字段是自动生成的,那也是
C#中的语法糖了,不用注脚字段,只用申明属性,编译器会自动生成相应字段。

关于 C# 的语法糖可以点击那篇博客【 C#
中的语法糖

C#,至于 ILDASM 的安装与行使可以点击那篇博客【ILDASM
的拉长和选用

以字符串为角标, 这一点就和数组分化等了:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Dynamic;
using System.Collections;
//这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段 
namespace Demo1
{
    public class IndexerClass
    {
        //用string作为索引器下标的时候,要用Hashtable
        private Hashtable name = new Hashtable();
        //索引器必须以this关键字定义,其实这个this就是类实例化之后的对象
        public string this[string index]
        {
            get { return name[index].ToString(); }
            set { name.Add(index, value); }    
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IndexerClass Indexer = new IndexerClass();
            Indexer["A0001"] = "张三";
            Indexer["A0002"] = "李四";
            Console.WriteLine(Indexer["A0001"]);
            Console.WriteLine(Indexer["A0002"]);
        }
    }
}

 

索引器的重载,那一点就是性质的不等:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Dynamic;
using System.Collections;
//这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段 
namespace Demo1
{
    public class IndexerClass
    {
        private Hashtable name = new Hashtable();
        //1:通过key存取Values
        public string this[int index]
        {
            get { return name[index].ToString(); }
            set { name.Add(index, value); }
        }

        //2:通过Values存取key
        public int this[string aName]
        {
            get
            {
                //Hashtable中实际存放的是DictionaryEntry(字典)类型,如果要遍历一个Hashtable,就需要使用到DictionaryEntry
                foreach (DictionaryEntry d in name)
                {
                    if (d.Value.ToString() == aName)
                    {
                        return Convert.ToInt32(d.Key);
                    }
                }
                return -1;
            }
            set { name.Add(value, aName); }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IndexerClass Indexer = new IndexerClass();
            //第一种索引器的使用
             Indexer[1] = "张三";//set访问器的使用
             Indexer[2] = "李四";
           Console.WriteLine("编号为1的名字:" + Indexer[1]);//get访问器的使用
             Console.WriteLine("编号为2的名字:" + Indexer[2]);
           Console.WriteLine();
           //第二种索引器的使用
             Console.WriteLine("张三的编号是:" + Indexer["张三"]);//get访问器的使用
             Console.WriteLine("李四的编号是:" + Indexer["李四"]);
           Indexer["王五"] = 3;//set访问器的使用
             Console.WriteLine("王五的编号是:" + Indexer["王五"]);
        }
    }
}

 

所有三个参数的索引器:

using System;
using System.Collections;
//这里的代码时参照自http://www.cnblogs.com/ArmyShen/archive/2012/08/27/2659405.html的代码片段 
namespace Demo1
{
    /// <summary>
    /// 入职信息类
    /// </summary>
    public class EntrantInfo
    {
        //姓名、编号、部门
        public string Name { get; set; }
        public int Num { get; set; }
        public string Department { get; set; }
    }

    /// <summary>
    /// 声明一个类EntrantInfo的索引器
    /// </summary>
    public class IndexerForEntrantInfo
    {
        private ArrayList ArrLst;//用于存放EntrantInfo类
        public IndexerForEntrantInfo()
        {
            ArrLst = new ArrayList();
        }

        /// <summary>
        /// 声明一个索引器:以名字和编号查找存取部门信息
        /// </summary>
        /// <param name="name"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public string this[string name, int num]
        {
            get
            {
                foreach (EntrantInfo en in ArrLst)
                {
                    if (en.Name == name && en.Num == num)
                    {
                        return en.Department;
                    }
                }
                return null;
            }
            set
            {
                ArrLst.Add(new EntrantInfo()
                {
                    Name = name,
                    Num= num,
                    Department = value
                });
            }
        }

        /// <summary>
        /// 声明一个索引器:以编号查找名字和部门
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public ArrayList this[int num]
        {
            get
            {
                ArrayList temp = new ArrayList();
                foreach (EntrantInfo en in ArrLst)
                {
                    if (en.Num == num)
                    {
                        temp.Add(en);
                    }
                }
                return temp;
            }
        }
        //还可以声明多个版本的索引器...
    }

    class Program
    {
        static void Main(string[] args)
        {
            IndexerForEntrantInfo Info = new IndexerForEntrantInfo();
            //this[string name, int num]的使用
             Info["张三", 101] = "人事部";
            Info["李四", 102] = "行政部";
            Console.WriteLine(Info["张三", 101]);
            Console.WriteLine(Info["李四", 102]);
            Console.WriteLine();
            //this[int num]的使用
            foreach (EntrantInfo en in Info[102])
            {
                Console.WriteLine(en.Name);
                Console.WriteLine(en.Department);
            }
        }
    }
}

相关文章