学习c#的第二十二天

目录

C# 索引器(Indexer)

表达式主体定义

索引器概述

使用索引器

备注

示例 1

可靠编程

接口中的索引器

属性和索引器之间的比较


C# 索引器(Indexer)

索引器是C#编程语言中的一个特性,它允许类或结构的实例像数组一样进行索引操作,而无需显式指定类型或实例成员。通过索引器,可以设置或检索特定索引位置的值。索引器类似于属性,但不同之处在于索引器的访问器需要使用参数。

下面是一个简单的示例,定义了一个泛型类,其中包含用于赋值和检索值的简单get和set访问器方法:

public class SampleCollection<T>
{private T[] arr = new T[100];public T this[int i]{get { return arr[i]; }set { arr[i] = value; }}
}

在上面的示例中,定义了一个名为SampleCollection的泛型类,该类包含一个私有的T类型数组arr,并且定义了一个索引器this,用于对arr数组进行索引操作。

下面是一个使用索引器的示例程序:

class Program
{static void Main(){var stringCollection = new SampleCollection<string>();stringCollection[0] = "Hello, ";stringCollection[1] = "world!";Console.Write(stringCollection[0] + stringCollection[1]);}
}

在上面的示例程序中,创建了SampleCollection类的一个实例stringCollection,并使用索引器对其进行赋值和检索操作。最终输出"Hello, world!"。

表达式主体定义

当索引器的 get 或 set 访问器包含一个简单的返回或设置值的语句时,可以使用表达式主体定义来简化代码。自C# 6起,表达式主体成员提供了一种经过简化的语法,使得只读索引器的实现变得更加简洁。以下是一个示例:

public class SampleCollection<T>
{private T[] arr = new T[100];public T this[int i] => arr[i];
}

在上面的示例中,我们定义了一个只读的索引器,使用了表达式主体定义。请注意,=> 引入了表达式主体,并未使用 get 关键字。这等价于下面的完整定义:

public class SampleCollection<T>
{private T[] arr = new T[100];public T this[int i]{get { return arr[i]; }}
}

通过使用表达式主体定义,可以将简单的只读索引器的实现代码变得更加简洁和易读。

自 C# 7.0 起,我们可以使用表达式主体定义来实现索引器的 get 和 set 访问器。对于只读索引器,我们可以使用简化的语法,不需要显式地使用 get 关键字。而对于读写索引器,需要同时使用 get 和 set 关键字。

下面是一个示例,展示了如何在 C# 7.0 及更新版本中使用表达式主体定义来实现只读和读写索引器:

public class SampleCollection<T>
{private T[] arr = new T[100];// 只读索引器的表达式主体定义public T this[int i] => arr[i];// 读写索引器的表达式主体定义public T this[int i]{get => arr[i];set => arr[i] = value;}
}

在这个示例中,我们展示了使用表达式主体定义来实现只读和读写索引器。对于只读索引器,我们可以省略显式的 get 关键字;而对于读写索引器,需要同时使用 get 和 set 关键字。

索引器概述

  • 使用索引器可以用类似于数组的方式为对象建立索引。

  • get 取值函数返回值。 set 取值函数分配值。

  • this 关键字用于定义索引器。

  • value 关键字用于定义由 set 访问器分配的值。

  • 索引器不必根据整数值进行索引;由你决定如何定义特定的查找机制。

  • 索引器可被重载。

  • 索引器可以有多个形参,例如当访问二维数组时。

使用索引器

索引器使你可从语法上方便地创建类、结构或接口,以便客户端应用程序可以像访问数组一样访问它们。 编译器将生成一个 Item 属性(或者如果存在 IndexerNameAttribute,也可以生成一个命名属性)和适当的访问器方法。 在主要目标是封装内部集合或数组的类型中,常常要实现索引器。 例如,假设有一个类 TempRecord,它表示 24 小时的周期内在 10 个不同时间点所记录的温度(单位为华氏度)。 此类包含一个 float[] 类型的数组 temps,用于存储温度值。 通过在此类中实现索引器,客户端可采用 float temp = tempRecord[4] 的形式(而非 float temp = tempRecord.temps[4])访问 TempRecord 实例中的温度。 索引器表示法不但简化了客户端应用程序的语法;还使类及其目标更容易直观地为其它开发者所理解。

若要在类或结构上声明索引器,请使用 this 关键字,如以下示例所示:

// 索引器声明
public int this[int index]
{// 获取和设置访问器
}

注意:通过声明索引器,可自动在对象上生成一个名为 Item 的属性。 无法从实例成员访问表达式直接访问 Item 属性。 此外,如果通过索引器向对象添加自己的 Item 属性,则将收到 CS0102 编译器错误。 要避免此错误,请使用 IndexerNameAttribute 来重命名索引器,详细信息如下所示。

备注

索引器及其参数的类型必须至少具有和索引器相同的可访问性。 有关可访问性级别的详细信息,请参阅访问修饰符。

有关如何在接口上使用索引器的详细信息,请参阅接口索引器。

索引器的签名由其形参的数目和类型所组成。 它不包含索引器类型或形参的名称。 如果要在相同类中声明多个索引器,则它们的签名必须不同。

索引器未分类为变量;因此,索引器值不能按引用(作为 ref 或 out 参数)传递,除非其值是引用(即按引用返回。)

若要使索引器的名称可为其他语言所用,请使用 System.Runtime.CompilerServices.IndexerNameAttribute,如以下示例所示:

// Indexer declaration
[System.Runtime.CompilerServices.IndexerName("TheItem")]
public int this[int index]
{// get and set accessors
}

此索引器被索引器名称属性重写,因此其名称将为 TheItem。 默认情况下,默认名称为 Item。

示例 1

using System;public class SampleCollection<T>
{private T[] arr = new T[100];// 定义索引器public T this[int i]{get { return arr[i]; }set { arr[i] = value; }}
}public class Program
{public static void Main(){// 创建SampleCollection实例SampleCollection<string> collection = new SampleCollection<string>();// 设置索引器的值collection[0] = "Hello";collection[1] = "World";// 获取索引器的值string firstElement = collection[0];string secondElement = collection[1];// 输出结果Console.WriteLine(firstElement);   // 输出: HelloConsole.WriteLine(secondElement);  // 输出: World}
}

在上述示例中,我们定义了一个名为 SampleCollection 的泛型类,它具有一个内部数组 arr,长度为100。然后,我们通过定义索引器使得可以像访问数组一样访问 SampleCollection 实例的元素。

在 Main 方法中,我们创建了 SampleCollection<string> 类的实例 collection。通过设置索引器的值,我们将字符串 "Hello" 和 "World" 分别赋值给索引 0 和索引 1 的元素。然后,我们通过获取索引器的值,将其赋值给 firstElement 和 secondElement 变量。

最后,我们将 firstElement 和 secondElement 的值输出到控制台,验证索引器的使用结果。

可靠编程

提高索引器的安全性和可靠性有两种主要方法:

  • 请确保结合某一类型的错误处理策略,以处理万一客户端代码传入无效索引值的情况。 在本主题前面的第一个示例中,TempRecord 类提供了 Length 属性,使客户端代码能在将输入传递给索引器之前对其进行验证。 也可将错误处理代码放入索引器自身内部。 请确保为用户记录在索引器的访问器中引发的任何异常。

  • 在可接受的程度内,为 get 和 set 访问器的可访问性设置尽可能多的限制。 这一点对  set 访问器尤为重要。 有关详细信息,请参阅限制访问器可访问性。

接口中的索引器

在C#中,接口是抽象类的一种形式,它定义了一个类或结构体应遵循的成员列表。然而,在接口中并不能直接包含字段,因此无法在接口中定义索引器。索引器必须与具体的实现相关联,而接口只能定义方法、属性、事件和索引器的成员契约,而不包含实际的实现。

换句话说,接口可以定义一个索引器的契约,但具体的实现需要在实现接口的类中完成。下面是一个示例:

using System;public interface IIndexable
{// 索引器的契约string this[int index] { get; set; }
}public class MyCollection : IIndexable
{private string[] _data = new string[100];// 实现接口中定义的索引器public string this[int index]{get { return _data[index]; }set { _data[index] = value; }}
}public class Program
{public static void Main(){MyCollection collection = new MyCollection();collection[0] = "Hello";collection[1] = "World";Console.WriteLine(collection[0]);  // 输出: HelloConsole.WriteLine(collection[1]);  // 输出: World}
}

在上述示例中,我们定义了一个名为 IIndexable 的接口,其中包含了一个索引器的契约。然后,在 MyCollection 类中,我们实现了 IIndexable 接口,并提供了对应的索引器实现。

通过这种方式,我们可以在接口中定义索引器的契约,然后在实现接口的类中完成对索引器的具体实现。这样做的好处是,当多个类需要实现相同的索引器行为时,可以通过接口来统一规范,从而提高代码的可维护性和扩展性。

属性和索引器之间的比较

索引器与属性在许多方面相似,但确实存在一些重要的差异。以下是这两者之间的主要区别:

  1. 访问方式:属性通过使用简单的名称来访问,而索引器使用索引来访问。属性可以像访问字段一样进行访问,而索引器使用类似于数组的语法来访问集合中的元素。

  2. 成员类型:属性可以是静态成员或实例成员,而索引器只能是实例成员。这意味着索引器只能通过实例对象进行访问。

  3. 参数:属性的get访问器没有参数,而索引器的get访问器具有与索引器相同的形参列表,以便接受索引参数。同样,属性的 set 访问器具有一个隐式的 value 参数,而索引器的 set 访问器也具有与索引器相同的形参列表,包括 value 参数。

  4. 简洁语法:对于属性,可以使用 自动实现的属性 来提供简洁的语法,而索引器只支持expression-bodied成员的简洁语法。

综上所述,尽管属性和索引器有许多相似之处,但它们在访问方式、成员类型、参数和语法等方面存在一些重要的差异。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/149122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Arcgis js Api日常天坑问题3——加载geojson图层,元素无属性

Arcgis js api加载geojson的方法 GeoJSONLayer | API Reference | ArcGIS Maps SDK for JavaScript 4.28 | ArcGIS Developers 按照上面的方法&#xff0c;点击元素查询后&#xff0c;发现不带属性。 解决方法很简单&#xff0c;添加属性outFileds&#xff08;如下&#xff…

HTML易忽略的角落【目录】

目前已有文章 **** 篇 本专栏是汇集了一些HTML常常被遗忘的知识&#xff0c;这里算是温故而知新&#xff0c;往往这些零碎的知识点&#xff0c;在你开发中能起到炸惊效果。我们每个人都没有过目不忘&#xff0c;过久不忘的本事&#xff0c;就让这一点点知识慢慢渗透你的脑海。 …

一句话总结敏捷实践中不同方法

敏捷实践是指一组优先考虑灵活性、协作和客户满意度的软件开发和项目管理原则和方法。 不同方法论的敏捷实践&#xff1a; 1、敏捷&#xff1a; Sprints&#xff1a;限时迭代&#xff08;通常 2-4 周&#xff09;&#xff0c;在此期间创建潜在的可交付产品增量。每日站立会议…

用js切割文字,超出省略

因为项目需要,当人员超过两个事则进行超出省略,如将一个 “张三,李四,王五”,这样的字串切割成"张三,李四…" 效果: 主要用的是基础的切割法 isOutlier(text) {if (!text || text "") return;const parts text.split(","); // 使用逗号将字…

【canvas】了解canvas,并实现会议预定记录钟表盘、页面水印

初识canvas Canvas 有什么用 Canvas 允许使用直线、曲线、矩形、圆形等基本图形绘制出复杂的图形 Canvas 可以加载图像&#xff0c;并进行各种处理&#xff0c;如裁剪、缩放、旋转等操作 Canvas 可以通过 JavaScript 控制&#xff0c;所以你可以利用帧动画原理&#xff0c;…

QPair的介绍及用法

QPair是一个模板类&#xff0c;它存储一对值&#xff08;key&#xff0c;value&#xff09;&#xff0c;可以是不同的数据类型。QPair的用法有以下几个方面&#xff1a; QPair的构造函数有以下几种形式&#xff1a; QPair()&#xff1a;默认构造函数&#xff0c;创建一个空的QP…

Leetcode2937. 使三个字符串相等

Every day a Leetcode 题目来源&#xff1a;2937. 使三个字符串相等 解法1&#xff1a;枚举 设 len1、len2、len3 分别为字符串 s1、s2、s3 的长度。 min_len 是 3 个字符串长度的最小值。 枚举 len min_len 到 len 1&#xff0c;设 t1、t2、t3 分别是字符串 s1、s2、s…

全链路监控--pinpoint

一、pinpoint架构原理 架构组成 Pinpoint Agent:和自己运行的应用关联起来的探针 Pinpoint Collector:收集各种性能数据 Pinpoint-Web: 将收集到的数据显成为 WEB网页显示 HBase Storage: 存储收集到的数据 工作原理 pinpoint的核心思想是在各个服务节点之间彼此调用时&a…

flask创建步骤

1.在__init__.py中创建db对象 from flask_sqlalchemy import SQLAlchemy db SQLAlchemy()2.同样的在__init__.py中create_app函数中让app传入到db中 def create_app():app Flask(__name__)app.config.from_object(settings.DevelopmentConfig)app.register_blueprint(ac)ap…

Unity 6 是下一个 LTS 版本即将发布

Unity 公司宣布&#xff0c;即将发布 Unity 6&#xff0c;并表示其为下一个长期支持版本 (LTS)。 Unity 在大会上演示了全新的 Unity 6引擎&#xff0c;并通过 Syncy Studios 采用 Unity 6 制作的《幻想王国&#xff08;Fantasy Kingdom&#xff09;》Demo 进行了演示&#xff…

面试题 三

一、this 手写call //1、定义myCall方法 //3、接收剩余参数并返回结果 Function.prototype.myCall function (thisArg, ...arg) {// console.log(thisArg); //person对象// console.log(this); //func方法//2、设置this并调用原函数//下面三行代码有个缺陷就是如果pers…

JS算法练习 11.20

leetcode 2629 复合函数 请你编写一个函数&#xff0c;它接收一个函数数组 [f1, f2, f3&#xff0c;…&#xff0c; fn] &#xff0c;并返回一个新的函数 fn &#xff0c;它是函数数组的 复合函数 。 [f(x)&#xff0c; g(x)&#xff0c; h(x)] 的 复合函数 为 fn(x) f(g(h(…

「Verilog学习笔记」边沿检测

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1ns module edge_detect(input clk,input rst_n,input a,output reg rise,output reg down );reg a_tem ; always (posedge clk or negedge rst_n) beginif…

Spark作业串行与并行提交job

在Scala中&#xff0c;您可以以串行和并行的方式提交Spark作业。看看如何使用for和par.foreach构造对应的例子。 串行Spark作业&#xff08;使用for&#xff09; // 串行Spark作业设置 for (tag <- tags) {spark.sparkContext.setJobGroup(tag.toString, s"Tag: $tag…

分布式原理

目录 1. 分布式原理1.1. 关系型数据库遵循 ACID 规则1.2. 分布式系统1.2.1. 分布式计算的优点1.2.2. 分布式计算的缺点 1.3. CAP 定理 (CAP theorem)1.4. BASE1.5. ACID vs BASE 1. 分布式原理 1.1. 关系型数据库遵循 ACID 规则 事务在英文中是 transaction, 和现实世界中的交…

我的256天创作纪念日

今天是我成为创作者的第256天纪念日&#xff0c;感谢CSDN官方的纪念信让我铭记这特殊的一天。 机缘 256天前&#xff0c;我怀着满满的好奇和期待&#xff0c;开始了我在CSDN的创作之旅。当时的我&#xff0c;是一个内向的计算机小白&#xff0c;对于写博客这件事还一无所知。…

Windows10 MYSQL Installer 安装(mysql-installer-community-5.7.19.0.msi)

分类 编程技术 1.进入官网找到自己所需的安装包&#xff1a;https://dev.mysql.com/ &#xff0c;路径&#xff1a;DOWNLOAD-->MYSQL Community Edition(GRL)-->MYSQL on Windows (Installer & Tool) 或直接点击 MySQL :: Download MySQL Installer 查看最新版本。…

uniapp+vue+Springboot 公司网站0~1搭建 前端前期设计篇

原型图 client https://www.xiaopiu.com/h5/byId?typeproject&id653bc791940bbb14e4feeecf admin 客户端 apph5 页面 首页展示 经典用户案例轮播图设计师轮播图 经典用户案例 经典案例搜索详情经典案例详情 设计师查询&#xff08;待定&#xff09; 后台管理 ​ …

bhosts 显示节点 “unreach“ 状态

4.1、bhosts简单使用 查看各节点情况&#xff0c;包括状态和正在运行的 Job 情况等 STATUS列展示节点状态 OK&#xff1a;可用——可接受新的作业的正常状态 unavail&#xff1a;不可用 可能原因&#xff1a;主机关闭&#xff0c;LIM和sbatchd不可达 unreach&#xff1a;无法连…

【笔记1-2】Qt系列:QkeyEvent 键盘事件 设定快捷键

参考文献 QKeyEvent 类用来描述一个键盘事件。当键盘按键被按下或者被释放时&#xff0c;键盘事件便会被发送给拥有键盘输人焦点的部件。QKeyEvent 的 key() 函数可以获取具体的按键关键字。需要特别说明的是&#xff0c;回车键在这里是 Qt::Key_Return&#xff1b;键盘上的一…