索引器的详细讲解(C#)

索引器与属性很类似。索引器的创建与属性创建所使用的编程语言特性是一样的。索引器使属性被索引:使用一个或多个参数引用的属性,这些参数为某些值集合提供索引。

索引器语法
可以通过变量名和方括号访问索引器。将索引器参数放入方括号内:

var item = SomeObject["key"];
SomeObject["keyOther"] = item;
使用this关键字作为属性名声明索引器,并在方括号内声明参数:
public int this[string Key]
{
       get => storage.Find[Key];
       set { storage.Set(Key, value); }
}

索引器可以使用任何有效的访问修饰符(public、protected internal、protected、internal、private、private protected)。它们可能是密封、虚拟或者抽象的。与属性一样,可以在索引器中为get和set访问器指定不同的访问修饰符。还可以指定只读索引器(忽略set访问器)或只写索引器(忽略get访问器)。
属性的各种用法同样适用于索引器(唯一例外的是“自动实现属性”,编译器无法始终为索引器生成正确的存储)。

创建索引器的必备要素:

  1. 必须先创建索引器所需要的容器(可以理解为数据的存放);
  2. 创建索引器需要使用this关键字;
  3. 索引器中必须包含get和set访问器,在C# 7.0后可以使用表达式(=>)主体进行简化;
  4. 在使用表达式主体成员进行索引时,必须额外的提供容器的修改接口(因为表达式主体不包括set访问器)。

索引器相当于一个方法,支持多个或多种类型的参数,与方法不同的是,索引器没有独立的名称,只能通过返回值的不同和参数的不同来区分不同的签名(从而实现重载),其返回值不能为void。索引器除了可以传入参数外,还可以对其进行赋值。
创建索引器时,其返回值为value关键字所使用的类型,定义了返回值类型的同时,也定义了其可接受的值类型。
总之,我对索引器的理解就是:是一个可以进行读写操作的自定义类中数据集合的接口。通过该接口,简化或丰富了该自定义类中数据集合的操作方式。

例如,在如下示例中,此索引器使用List作为容器,使用int类型的index进行索引,返回值为Measurements对象。

public class DataSamples
    {
        private class Page
        {
            private readonly List<Measurements> pageData = new List<Measurements>();
            private readonly int startingIndex;
            private readonly int length;
            private bool dirty;
            private DateTime lastAccess;
            public Page(int startingIndex, int length)
            {
                this.startingIndex = startingIndex;
                this.length = length;
                lastAccess = DateTime.Now;

                var generator = new Random();
                for(int i = 0; i < length; i++)
                {
                    var m = new Measurements
                    {
                        HiTemp = generator.Next(50, 95),
                        LoTemp = generator.Next(12, 49),
                        AirPressure = 28.0 + generator.NextDouble() * 4
                    };
                    pageData.Add(m);
                }
            }
            public bool HasItem(int index) =>
                ((index >= startingIndex) && (index < startingIndex + length));
            public Measurements this[int index]
            {
                get
                {
                    lastAccess = DateTime.Now;
                    return pageData[index - startingIndex];
                }
                set
                {
                    pageData[index - startingIndex] = value;
                    dirty = true;
                    lastAccess = DateTime.Now;
                }
            }
            public bool Dirty => dirty;
            public DateTime LastAcess => lastAccess;
        }

        private readonly int totalSize;
        private readonly List<Page> pageInMemory = new List<Page>();

        public DataSamples(int totalSize)
        {
            this.totalSize = totalSize;
        }

        public Measurements this[int index]
        {
            get
            {
                if (index < 0)
                    throw new IndexOutOfRangeException("index不能小于0!");
                if (index >= totalSize)
                    throw new IndexOutOfRangeException("index大小超出存储空间!");
                var page = updateCachedPagesForAccess(index);
                return page[index];
            }
            set
            {
                if (index < 0)
                    throw new IndexOutOfRangeException("index不能小于0!");
                if(index >= totalSize)
                    throw new IndexOutOfRangeException("index大小超出存储空间!");
                var page = updateCachedPagesForAccess(index);
                page[index] = value;
            }
        }

        private Page updateCachedPagesForAccess(int index)
        {
            foreach(var p in pageInMemory)
            {
                if (p.HasItem(index))
                    return p;
            }
            var startingIndex = (index / 1000) * 1000;
            var newPage = new Page(startingIndex, 1000);
            addPageToCache(newPage);
            return newPage;
        }

        private void addPageToCache(Page p)
        {
            if(pageInMemory.Count > 4)
            {
                var oldest = pageInMemory
                    .Where(page => !page.Dirty)
                    .OrderBy(page => page.LastAcess)
                    .FirstOrDefault();
                if (oldest != null)
                    pageInMemory.Remove(oldest);
            }
            pageInMemory.Add(p);
        }
    }

上面的例子中,仅仅是对于索引器的认识,在实际工作中使用价值不大,因为所做的操作完全可以使用.NET中预定义的数据集合来完成。我个人觉得索引器的最大价值在于get和set访问器中数据操作的自定义处理,可以在访问器中对数据进行过滤或修正。

索引器总结:

  1. 使用索引器可以类似于数组的方式为对象建立索引;
  2. get取函数返回值,set取函数分配值;
  3. this(代表当前类)关键字用于定义索引器;
  4. value关键字用于定义set索引器所赋予的值;
  5. 索引器不必根据整数值进行索引,自行决定如何定义特定的查找机制;
  6. 索引器可以被重载;
  7. 索引器可以有多个形参,例如对二维数组的访问。
  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
学习安排:4周4个项目实战 学习形式:录播视频+在线作业考核+助教一对一辅导答疑 1. C#基本语法:基本编程(If:…else)语句、数组等。2. C#面向对象编程:封装、继承、多态性、面向接口编程、动态多态性、字符串基础等。3. .Net 框架原理讲解:多维数组、可变参数 Params、类的实例化内存分配机制等。4. 深入学习对象类型:里氏替换原则(LSP)、类的属性极其本质特性、IS ,AS 关键字、深入学习字符串理论、枚举类型以及适用场合。5. 深入学习集合特性:索引、自定义集合、深入刨析集合类型本质(ArrayList、HashTable)、学习泛型集合、泛型约束等。6. 学习委托与事件:委托与事件的区别、匿名方法、Lambda表达式。7. 正则表达式。8. 查询表达式Linq。9. 反射、特性、动态编程。10. 多线程编程。11. Socket通讯技术。 第二模块:Unity 入门与基础 学习安排:4周3个项目实战 学习形式:录播视频+在线作业考核+助教一对一辅导答疑 课程内容:游戏与Unity发展历史概述、 3D 模型基础、 地形编辑、光源、音频、Unity脚本程序基础、GUI、3D模型动画的导入 与基本应用、物理学模拟(初级)、碰撞盒与触发、协程、SendMessage数据传值技术等。 学习安排:4周4个项目实战 学习形式:录播视频+在线作业考核+助教一对一辅导答疑 课程内容:讲解粒子系统、Mecanim、导航寻路、Unity游戏移植技术、Mecanim 动画系统、导航寻路、项目研发常用优化策略、Unity游戏移植与手指触控识别、射线、数据持久化、对象缓冲池技术、物理学模拟(铰链关节(Hinge Joint)、弹簧关节 、固定关节、角色关节)与资源动态加载技术(AssetBundle与WWW)等。 第四模块:Unity项目实训: ARPG项目"地下守护神" 学习安排:4周1个项目实战 学习形式:录播视频+在线作业考核+助教一对一辅导答疑 课程内容:1:前端分层的MVC架构搭建,开发自定义的资源动态加载插件、音频插件、对话系统插件、事件监听插件等。2: UI粒子特效、场景淡入淡出控制。3: 单机与移动端的双输入控制系统开发。4: 数值平衡处理与开发。5: 多种设计模式在游戏研发过程中的灵活运用。6: XML技术的灵活运用,在系统解耦与资源国际化方面的技术突破。7: 开发强大灵活的日志系统插件,应对服务与移动端的各种复杂系统调试需求。8:开发“对话系统”,与“新手导航”。9:开发基于XML的对象持久化技术。10:开发“背包系统”、“商城系统”、“公告系统”、“任务系统”。11:开发“副本”多种类怪物的战斗系统。12:开发各种战斗特效系统: “血条”、“漂字”、“连击”等功能。 第五模块:虚拟现实(VR)与增强现实技术(AR) 学习安排:1周2个项目实战 学习形式:录播视频+在线作业考核+助教一对一辅导答疑 课程内容:R虚拟现实技术开发:先从什么是虚拟现实(VR)、虚拟现实的主要特点、虚拟现实技术的基础底层原理、国际与国内的产业布局、国际权威机构未来发展趋势预测等讲起。然后主要介绍国际主要领军品牌:Oculus、HTC、SonyVR等产品规格、主要性能指标等。最后重点以一款国内著名VR产品:3Glasses 为代表,介绍VR产品的具体使用、维护、与开发项目全过程流程等。AR 增强实现开发讲解什么是增强现实、注册高通AR账号、制作识别图、SDK下载与制作、打包发布

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值