C# 中常用的索引器
使用 C# 中的索引器和 JavaScript 中访问对象的属性是很相似。
之前了解过索引器,当时还把索引器和属性给记混了, 以为索引器就是属性,下面写下索引器和属性的区别,以及怎么使用索引器
先说明一点,这里的索引器和数据库中的索引不一样,虽然都是找元素。
索引器和属性的区别:
- 属性和索引器都是函数,但是表现形式不一样;(属性和索引器在代码的表现形式上和函数不一致,但其本质都是函数,需要通过 ILDASM 来查看,或者使用反射)
- 索引器可以被重载,而属性没有重载这一说法;(索引器的重载即方括号中的类型不同)
- 索引器不能声明为static,而属性可以;(索引器之所以不能声明为 static,因为其自身携带 this 关键字,需要被对象调用)
还有一点就是索引很像数组,它允许一个对象可以像数组一样被中括号 [] 索引,但是和数组有区别,具体有:
- 数组的角标只能是数字,而索引器的角标可以是数字也可以是引用类型;
- 数组是一个引用类型的变量,而索引器是一个函数;
我在代码中很少自己定义索引器,但是我却经常在用它,那是因为系统自定义了很多索引器,比如 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 文件,如下图:

从中我们可以看到一个 Add 的方法,
这个小图标代表着方法,一共有 6 个方法,其中 .ctor 暂时不管,Add 方法是我们自己写的,
get_Age : int32(),这个方法是属性 age 的读方法,对应的还有个写方法;
还剩下两个就是索引器生成的方法了,get_Item:string(int32) 和 set_Item : void(int32) ;
还有这样的图标
,这个图标是代表着字段,上面的两个字段是自动生成的,这也是 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);
}
}
}
}
C# 中常用的索引器的更多相关文章
- keras中常用的初始化器
keras中常用的初始化器有恒值初始化器.正态分布初始化器.均匀分布初始化器 恒值初始化器: keras.initializers.Zeros() keras.initializers.Ones() ...
- C#中如何应用索引器 ( How to use Indexers )
C#中索引器是个好东西, 可以允许类或者结构的实例像数组一样进行索引. 在foreach或者直接索引时很有用. 使用索引器可以简化客户端代码, 即调用者可以简化语法,直观理解类及其用途. 索引器只能根 ...
- 使用 Vue + TypeScript 时项目中常用的装饰器
目录 一.@Component 装饰器 1)父组件 2)子组件 二. @Emit 装饰器 1)父组件 2)子组件 三. @Model 装饰器 1)父组件 2)子组件 四. @Prop 装饰器 1)父组 ...
- C# 索引器的理解和使用
概述 此部分内容引用自MSDN文档 使用索引器可以用类似于数组的方式为对象建立索引. get 取值函数返回值. set 取值函数分配值. this 关键字用于定义索引器. value 关键字用于定义 ...
- C#中的索引器的简单理解和用法
索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了数组和集合成员时,索引器 ...
- C#中索引器Indexer的学习使用
索引器 顾名思义,是用来索引的,那么C#中索引器是用来索引什么的呢 首先我们知道,C#中的数组是本身就可以索引的,那么C#中的类和结构呢,类和结构的实例是无法索引的,如果我们想让C#中类或者结构的实例 ...
- C#类索引器的使用
索引器提供了一种可以让类被当作数组进行访问的方式.在C#中,类索引器是通过this的属性实现的.index.ToString("D2")将index转换成一个具有两个字符宽度的字符 ...
- C# 索引器简介
索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,是程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了数组和集合成员时,索引器 ...
- ylbtech-LanguageSamples-Indexers(索引器)
ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-Indexers(索引器) 1.A,示例(Sample) 返回顶部 “索引器”示例 本示 ...
随机推荐
- A1050
输入两个字符串,将第一个字符串中包含的第二个字符串的字符去掉(包括空格),然后输出. gets()不能用了,我混搭了string和length(),不用纠结长度还是很好的. 第二个字符串所在HashT ...
- extjs+MVC4+PetaPoco+AutoFac+AutoMapper后台管理系统(附源码)
前言 本项目使用的开发环境及技术列举如下:1.开发环境IDE:VS2010+MVC4数据库:SQLServer20082.技术前端:Extjs后端:(1).数据持久层:轻量级ORM框架PetaPoco ...
- python中利用少量代码快速实现从类对象中抽取所需属性的一种实践
项目中有可能会碰到这样一种场景: 根据一个id,查询得到和id对应的完整数据信息存储对象,比如书籍id到书籍详细信息,用户id到用户详细信息等,详细信息字段可能包括几十甚至上百个数据字段,真正需要返回 ...
- P1208 [USACO1.3]混合牛奶 Mixing Milk
P1208 [USACO1.3]混合牛奶 Mixing Milk 题目描述 由于乳制品产业利润很低,所以降低原材料(牛奶)价格就变得十分重要.帮助Marry乳业找到最优的牛奶采购方案. Marry乳业 ...
- 3D Touch初探
伴着6S的发布,iOS 9.0开始支持3D Touch功能.使用场景来分一共有三种情况. 一.基于UIViewController的扩展 1. 首先要注册需要监听重按手势的 source view: ...
- PHP中URL字符串与关联数组的互相转换
转换PHP数组为查询字符串放到URL中 $data = array( 'apikey'=>'xg6tr7k', 'user'=>'abcd', 'email'=>'root@exam ...
- jsp传递参数的四种方法
1.form表单 2.request.setAttribute();和request.getAttribute(); 3.超链接:<a herf="index.jsp"?a= ...
- docker 应用场景
内容来自知乎.先mark,后续再研究 0.无痛尝试新事物 这应该是最早让我感受到docker的便利性的使用场景了. 以前,如果想尝试新的编程语言/数据库/命令行工具,会先找找apt的源里有没有相应的包 ...
- 新买的 SSD 固态硬盘竟然是坏的,我傻了啊!
1. 今天早上上班路上在网上下单了一个 1 T 的 SSD 固态硬盘,晚上 7 点半左右送到手后迫不及待想替换掉原来的机械硬盘,在这个新硬盘上装系统,玩起来. 2. 拆开包装,先用移动硬盘接口检查下新 ...
- 模拟实现MyBatis中通过SQL反射实体类对象功能
话不多说,直接上干货! package cn.test; import java.lang.reflect.Method; import java.sql.Connection; import jav ...