C# 索引器

本文档根据 C# 编程指南 改编而成。主要介绍以下内容。
使用索引器
接口中的索引器
属性与索引器区别

索引器

索引器允许类或结构的实例就像数组一样进行索引。 无需显式指定类型或实例成员,即可设置或检索索引值。 索引器类似于属性,不同之处在于它们的访问器需要使用参数。

  • 使用索引器可以用类似于数组的方式为对象建立索引。
  • get 取值函数返回值。 set 取值函数分配值。
  • this 关键字用于定义索引器。
  • value 关键字用于定义 set 索引器所赋的值。
  • 索引器不必根据整数值进行索引;由你决定如何定义特定的查找机制。
  • 索引器可被重载。
  • 索引器可以有多个形参,例如当访问二维数组时。

使用索引器

索引器使你可从语法上方便地创建类、结构或接口,以便客户端应用程序能像访问数组一样访问它们。 在主要目标是封装内部集合或数组的类型中,常常要实现索引器。

示例

class TempRecord
{
    // Array of temperature values
    private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 
                                            61.3F, 65.9F, 62.1F, 59.2F, 57.5F };

    // To enable client code to validate input 
    // when accessing your indexer.
    public int Length
    {
        get { return temps.Length; }
    }
    // Indexer declaration.
    // If index is out of range, the temps array will throw the exception.
    public float this[int index]
    {
        get
        {
            return temps[index];
        }

        set
        {
            temps[index] = value;
        }
    }
}

class MainClass
{
    static void Main()
    {
        TempRecord tempRecord = new TempRecord();
        // Use the indexer's set accessor
        tempRecord[3] = 58.3F;
        tempRecord[5] = 60.1F;

        // Use the indexer's get accessor
        for (int i = 0; i < 10; i++)
        {
            System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
        }

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();

    }
}

使用其他值进行索引

C# 不将索引参数类型限制为整数。

例如,对索引器使用字符串可能有用。 通过搜索集合内的字符串并返回相应的值,可以实现此类索引器。 由于访问器可被重载,字符串和整数版本可以共存。

接口中的索引器

可以在接口上声明索引器。 接口索引器的访问器与类索引器的访问器有所不同,差异如下:

  • 接口访问器不使用修饰符。
  • 接口访问器没有正文。

因此,访问器的用途是指示索引器为读写、只读还是只写。

下面是接口索引器访问器的示例:

// Indexer on an interface:
public interface ISomeInterface
{
    // Indexer declaration:
    int this[int index]
    {
        get;
        set;
    }
}

// Implementing the interface.
class IndexerClass : ISomeInterface
{
    private int[] arr = new int[100];
    public int this[int index]   // indexer declaration
    {
        get
        {
            // The arr object will throw IndexOutOfRange exception.
            return arr[index];
        }
        set
        {
            arr[index] = value;
        }
    }
}

class MainClass
{
    static void Main()
    {
        IndexerClass test = new IndexerClass();
        System.Random rand = new System.Random();
        // Call the indexer to initialize its elements.
        for (int i = 0; i < 10; i++)
        {
            test[i] = rand.Next();
        }
        for (int i = 0; i < 10; i++)
        {
            System.Console.WriteLine("Element #{0} = {1}", i, test[i]);
        }

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}

注意:当类采用相同的索引签名实现多个接口时,需用完全限定名称以避免歧义

详情见示例

    // Indexer on an interface:
    public interface ISomeInterface
    {
        // Indexer declaration:
        string this[int index]
        {
            get;
            set;
        }
    }

    public interface ICitizen
    {
        string this[int index]
        {
            get;
            set;
        }
    }

    // Implementing the interface.
    class IndexerClass : ISomeInterface, ICitizen
    {
        private string[] arr = new string[100];
        private string[] arr_str = new string[100];

        string ICitizen.this[int index]
        {
            get
            {
                return arr_str[index];
            }
            set
            {
                arr_str[index] = value;
            }
        }

        string ISomeInterface.this[int index]
        {
            get
            {
                // The arr object will throw IndexOutOfRange exception.
                return arr[index];
            }
            set
            {
                arr[index] = value;
            }
        }
    }

    class MainClass
    {
        static void Main()
        {

            Console.WriteLine("ISomeInterface\n");
            ISomeInterface test = new IndexerClass();
            System.Random rand = new System.Random();
            // Call the indexer to initialize its elements.
            for (int i = 0; i < 10; i++)
            {
                test[i] = Convert.ToString(rand.Next());
            }
            for (int i = 0; i < 10; i++)
            {
                System.Console.WriteLine("Element #{0} = {1}", i, test[i]);
            }

            Console.WriteLine("\nICitizen\n");
            ICitizen cities = new IndexerClass();
            System.Random rand1 = new System.Random();
            // Call the indexer to initialize its elements.
            for (int i = 0; i < 10; i++)
            {
                cities[i] = "hangzhou" + rand.Next();
            }
            for (int i = 0; i < 10; i++)
            {
                System.Console.WriteLine("Element #{0} = {1}", i, cities[i]);
            }


            // Keep the console window open in debug mode.
            System.Console.WriteLine("Press any key to exit.");

            System.Console.ReadKey();
        }
    }


属性与索引器的区别

索引器与属性相似。
除下表所示的差别外,对属性访问器定义的所有规则也适用于索引器访问器。

Proprety索引器
允许以将方法视作公共数据成员的方式调用方法。通过在对象自身上使用数组表示法,允许访问对象内部集合的元素。
通过简单名称访问。通过索引访问。
可为静态成员或实例成员。必须是实例成员。
属性的 get 访问器没有任何参数。索引器的 get 访问器具有与索引器相同的形参列表。
属性的 set 访问器包含隐式 value 参数。索引器的 set 访问器具有与索引器相同的形参列表,value 参数也是如此。
通过自动实现的属性支持简短语法。不支持简短语法。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值