之前瞭解過索引器,當時還把索引器和屬性給記混了, 以為索引器就是屬性,下麵寫下索引器和屬性的區別,以及怎麼使用索引器 先說明一點,這裡的索引器和資料庫中的索引不一樣,雖然都是找元素。 索引器和屬性的區別: 屬性是以名稱來標識,而索引器是以函數的形式來標識(但是索引器不能完全理解為函數); 索引器可以... ...
之前瞭解過索引器,當時還把索引器和屬性給記混了, 以為索引器就是屬性,下麵寫下索引器和屬性的區別,以及怎麼使用索引器
先說明一點,這裡的索引器和資料庫中的索引不一樣,雖然都是找元素。
索引器和屬性的區別:
- 屬性是以名稱來標識,而索引器是以函數的形式來標識(但是索引器不能完全理解為函數);
- 索引器可以被重載,而屬性沒有重載這一說法;
- 索引器不能聲明為static,而屬性可以;
還有一點就是索引很像數組,它允許一個對象可以像數組一樣被中括弧 [] 索引,但是和數組有區別,具體有:
- 數組的角標只能是數字,而索引器的角標可以是數字也可以是引用類型;
- 數組是一個變數,而索引器可以理解為一個函數;
我在代碼中很少自己定義索引器,但是我卻經常在用它,那是因為系統自定義了很多索引器,比如 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 ConsoleApplicationTest { public class IndexerClass { private string[] name = new string[2]; //索引器必須以this關鍵字定義,其實這個this就是類實例化之後的對象 public string this[int index] { //實現索引器的get方法 get { if (index < 2) { return name[index]; } return null; } //實現索引器的set方法 set { if (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的特殊位置。
以字元串為角標, 這點就和數組不一樣了:
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 ConsoleApplicationTest { 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 ConsoleApplicationTest { 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 ConsoleApplicationTest { /// <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); } } } }