0Pricing
C# Academy · 课时

支持范围的自定义类型

为自定义类型添加 Index 和 Range 支持。

支持范围的自定义类型 是 CoddyKit 上的免费 C# Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。

支持 Index 和 Range 的两种方式

您自己的类型也可以支持 Index 和 Range 语法。有两种实现方式:提供显式索引器,或提供 Length/Count 属性以及 Slice 方法。

显式 Index 索引器

添加一个接收 System.Index 的索引器后,^ 运算符就可以直接用于您的类型。

using System;

class Deck {
    private int[] cards = { 1, 2, 3, 4, 5 };
    public int this[Index i] => cards[i];
}

var d = new Deck();
Console.WriteLine(d[^1]); // 5

显式 Range 索引器

要支持使用 .. 进行切分,请添加一个接收 System.Range 并返回所需 slice 类型的索引器。

using System;

class Deck {
    private int[] cards = { 1, 2, 3, 4, 5 };
    public int[] this[Range r] => cards[r];
}

var d = new Deck();
Console.WriteLine(string.Join(",", d[1..3])); // 2,3

Length + Slice 模式

如果您的类型具有 Count 或 Length 属性以及 Slice(int start, int length) 方法,编译器也可以自动生成范围支持。

实现这一模式

这里的自定义缓冲区提供了 Length 和 Slice。编译器会为您将 buf[1..3] 重写为 buf.Slice(1, 2)。

using System;

class Buffer {
    private int[] data = { 10, 20, 30, 40 };
    public int Length => data.Length;
    public int this[int i] => data[i];
    public int[] Slice(int start, int length) {
        var result = new int[length];
        Array.Copy(data, start, result, 0, length);
        return result;
    }
}

var buf = new Buffer();
Console.WriteLine(string.Join(",", buf[1..3])); // 20,30

Length 为什么重要

Length(或 Count)属性让编译器能够在您的类型上解析 ^1 这样的从末尾索引。没有它,^ 就无法转换。

using System;

class Buffer {
    private int[] data = { 10, 20, 30, 40 };
    public int Length => data.Length;
    public int this[Index i] => data[i.GetOffset(Length)];
}

var buf = new Buffer();
Console.WriteLine(buf[^1]); // 40

手动解析 Index

在 Index 索引器内部,调用 i.GetOffset(Length),将可能从末尾开始的索引转换为普通偏移量。

using System;

class Ring {
    private string[] items = { "a", "b", "c" };
    public int Length => items.Length;
    public string this[Index i] {
        get {
            int offset = i.GetOffset(Length);
            return items[offset];
        }
    }
}

var r = new Ring();
Console.WriteLine(r[^2]); // b

手动解析 Range

对于 Range 索引器,r.GetOffsetAndLength(Length) 会同时提供要复制的起始位置和数量。

using System;

class Ring {
    private int[] items = { 1, 2, 3, 4, 5 };
    public int Length => items.Length;
    public int[] this[Range r] {
        get {
            var (start, len) = r.GetOffsetAndLength(Length);
            var slice = new int[len];
            Array.Copy(items, start, slice, 0, len);
            return slice;
        }
    }
}

var r = new Ring();
Console.WriteLine(string.Join(",", r[^3..^1])); // 3,4

Count 与 Length

这一模式接受任意一个名称:数组和跨度使用 Length;List<T> 使用 Count。任一属性都能满足编译器的要求。

using System;
using System.Collections.Generic;

var list = new List<int> { 1, 2, 3, 4 };
// List<T> has Count, so Index works:
Console.WriteLine(list[^1]); // 4

设计 Slice 的返回类型

请决定您的 Slice 返回副本(如数组)还是视图(如跨度)。视图的开销更低,但会共享可变状态,因此请记录这一选择。

完整的自定义类型

这个 Sequence 通过显式索引器和 Length 属性同时支持 ^ 和 ..。

using System;

class Sequence {
    private int[] data;
    public Sequence(int[] d) => data = d;
    public int Length => data.Length;
    public int this[Index i] => data[i];
    public int[] this[Range r] => data[r];
}

var s = new Sequence(new[] { 5, 10, 15, 20 });
Console.WriteLine(s[^1]);                       // 20
Console.WriteLine(string.Join(",", s[1..^1]));  // 10,15

快速检查

确认自定义类型支持范围语法的条件。

回顾

您已经学会了向自己的类型添加 Index/Range 支持的两种方式。

  • 提供接收 Index 和 Range 的显式索引器。
  • 使用隐式模式:提供 Count/Length 属性和 Slice(int, int)。
  • GetOffset(Length) 和 GetOffsetAndLength(Length) 可以解析从末尾开始的位置。

常见问题解答

「支持范围的自定义类型」课时是免费的吗?

是的 — 「支持范围的自定义类型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。

「支持范围的自定义类型」这节课中我会学到什么?

为自定义类型添加 Index 和 Range 支持。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「支持范围的自定义类型」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Index 类型与 ^ 运算符
  2. Range 类型与 .. 运算符
  3. 数组和字符串中的范围
  4. 支持范围的自定义类型
← 返回 C# Academy