目录
一、集合
.NET提供了一种称为集合的数据类型,类似于数组,是一组组合在一起的类型化对象,可以通过遍历获取其中的每个元素。相对于数组,它的存储空间是动态变化的,可以对其中的数据进行添加、删除、修改等操作。
集合需要使用System.Collections命名空间的集合接口来实现。该空间提供的常用的接口及说明:
1.IEnumerable和IEnumerator接口
IEnumerable接口用于公开枚举数,该枚举数支持在非泛型集合上进行简单迭代(迭代就是循环遍历,重复执行同一过程)。IEnumerable接口有一个GetEnumerator()方法,用来返回循环访问集合的枚举器。迭代集合时使用。
IEnumerable接口定义:
public interface IEnumerable
GetEnumerator()方法定义:
IEnumerator GetEnumerator()
在实现 IEnumerable接口的同时,还需要实现 IEnumerator接口。该接口支持对非泛型集合的简单迭代。它包括3个成员,分别是Current属性、MoveNext()方法和Reset()方法。
object Current{get} //获取集合中当前位置元素
bool MoveNext() //迭代集合中的下一个元素
void Reset() //设置为初始位置,位于集合中第一个元素的前面
(1)示例:通过自定义集合存储商品信息
继承 IEnumerable和IEnumerator接口并定义一个集合来存储商品信息,遍历输出集合中的商品信息。
// 集合
using System.Collections;
namespace _06
{
public class Goods(string code, string name) //定义集合中的元素类,表示商品信息类
{
public string Code = code; //编号
public string Name = name; //名称
}
public class JHClass : IEnumerable, IEnumerator //定义集合类
{
private readonly Goods[] _goods; //初始化Goods类型的集合
public JHClass(Goods[] gArray) //使用带参构造函数赋值
{
_goods = new Goods[gArray.Length];
for (int i = 0; i < gArray.Length; i++)
{
_goods[i] = gArray[i];
}
}
IEnumerator IEnumerable.GetEnumerator() //实现IEnumerable接口中GetEnumerator方法
{
return (IEnumerator)this;
}
int position = -1; //记录索引位置
object IEnumerator.Current //实现IEnumerator接口中的Current属性
{
get
{
return _goods[position];
}
}
public bool MoveNext() //实现IEnumerator接口中的MoveNext方法
{
position++;
return (position < _goods.Length);
}
public void Reset() //实现IEnumerator接口中的Reset方法
{
position = -1; //指向第一个元素
}
}
class Program
{
static void Main()
{
Goods[] goodsArray =
[
new("T0001", "HuaWei MateBook"),
new("T0002", "荣耀V30 5G"),
new("T0003", "华为平板电脑"),
]; //初始化Goods类型的集合
JHClass jhList = new(goodsArray); //使用数组创建集合类对象
foreach (Goods g in jhList) //遍历集合,此处Goods类不是集合Goods[]
Console.WriteLine(g.Code + " " + g.Name);
Console.ReadLine();
}
}
}
//运行结果:
/*
T0001 HuaWei MateBook
T0002 荣耀V30 5G
T0003 华为平板电脑 */
2.List和IList
List和IList之间的主要区别在于List是一个具体的类,它表示可以由索引访问的对象的列表;而IList是一个接口,它表示可以由索引访问的对象的集合。IList接口由两个接口实现,它们是ICollection和IEnumerable。
(1)示例1
// IList接口及与List的比较
namespace _IList
{
class IList_Program
{
static void Main(string[] args)
{
IList<string> ilist =
[
"Mark",
"John"
]; //IList可以由索引访问的对象的集合
List<string> list = []; //List可以由索引访问的对象的列表
list.Add("Mark");
list.Add("John");
foreach (string lst in list)
{
Console.WriteLine(lst);
}
Console.WriteLine();
Console.WriteLine("---对比---");
Console.WriteLine();
foreach (string lst in ilist)
{
Console.WriteLine(lst);
}
Console.ReadLine();
}
}
}
//运行结果:
/*
Mark
John
---对比---
Mark
John */
(2)示例2
IList Interface (System.Collections) | Microsoft Learn
https://learn.microsoft.com/zh-cn/dotnet/api/system.collections.ilist?view=net-8.0
二、索引器
C#支持一种名为索引器的特殊“属性”,索引器允许一个对象可以像数组一样被索引。索引器的声明方式与属性相似。
1.索引器与属性的区别
- 索引器在声明时需要使用this关键字定义参数,而属性不需要。
- 索引器的名称必须是关键字this,this之后一对[],在[]之间指定索引的参数列表,其中必须至少有一个参数。
- 索引器不能被定义为静态的,定义时不能使用static关键字。可用的修饰符有new、public、protected、internal、private、virtual、sealed、override、abstract、extern。
- 索引器的使用方式不同于属性的使用方式,需要使用元素访问运算符[],并在其中指定参数进行引用。
- 当索引器声明包含extern修饰符时,称为外部索引器,由于外部索引器声明不提供任何实现,所以它的每个索引器声明都由一个分号组成。
[修饰符][类型]this[参数列表]
{
get{get访问器体}
set{set访问器体}
}
2.示例:通过索引器访问元素
定义一个类,在类中声明索引器,在Main()方法中创建类的对象,通过索引器为数组元素赋值,遍历数组元素。
// 通过索引器访问类元素
namespace _07
{
/// <summary>
/// 创建类并在其中声明索引器
/// </summary>
class CollClass
{
public const int SIZE = 4; //表示数组的长度
private readonly string[] arrStr; //声明数组
public CollClass() //构造方法
{
arrStr = new string[SIZE]; //设置数组的长度
}
public string this[int index] //定义索引器
{
get
{
return arrStr[index]; //通过索引器取数组元素值
}
set
{
arrStr[index] = value; //通过索引器给数组元素赋值
}
}
}
class Program
{
/// <summary>
/// 通过索引器访问类中的元素
/// </summary>
static void Main(string[] args)
{
CollClass cc = new(); //创建CollClass类的对象=数组
cc[0] = "CSharp"; //通过索引器给数组元素赋值
cc[1] = "ASP.NET"; //通过索引器给数组元素赋值
cc[2] = "Python"; //通过索引器给数组元素赋值
cc[3] = "Java"; //通过索引器给数组元素赋值
for (int i = 0; i < CollClass.SIZE; i++) //遍历所有的元素
{
Console.WriteLine("cc[{0}] = {1}", i, cc[i]); //通过索引器取值
}
Console.Read();
}
}
}
//运行结果:
/*
cc[0] = CSharp
cc[1] = ASP.NET
cc[2] = Python
cc[3] = Java */
其它常用接口的用法及示例待作者完成创作和测试后逐渐发布。