Sobes.tech
Junior

Какви са индексите в C#? Какви видове индекси съществуват и сте ги използвали на практика?

sobes.tech AI

Отговор от AI

Индексиращите в C# позволяват да се обръщате към екземпляр на клас или структура като към масив, използвайки синтаксиса []. Те не са статични и пренатоварват оператора [].

Индексиращи

Индексиращите позволяват да се дефинира логика за достъп до елементи на колекция или структура данни вътре в клас.

public class MyCollection
{
    private string[] data = new string[10];

    // Индексатор, който позволява получаване или задаване на елемент по индекс
    public string this[int index]
    {
        get
        {
            // Проверка за граници
            if (index >= 0 && index < data.Length)
            {
                return data[index];
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
        set
        {
            // Проверка за граници
            if (index >= 0 && index < data.Length)
            {
                data[index] = value;
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
    }
}

Типове параметри на индексиращите

Индексиращите могат да приемат всякакъв брой параметри от всякакъв тип, не само цели числа.

public class DictionaryLike
{
    private Dictionary<string, string> _dictionary = new Dictionary<string, string>();

    // Индексатор с параметър тип string
    public string this[string key]
    {
        get
        {
            if (_dictionary.ContainsKey(key))
            {
                return _dictionary[key];
            }
            else
            {
                return null; // Или да хвърли изключение
            }
        }
        set
        {
            _dictionary[key] = value;
        }
    }
}

Пренатоварване на индексаторите

Могат да се създават пренатоварени индексатори с различни сигнатури (набори и типове параметри).

public class Matrix
{
    private int[,] data;

    public Matrix(int rows, int cols)
    {
        data = new int[rows, cols];
    }

    // Индексатор с два цели числа като параметри
    public int this[int row, int col]
    {
        get
        {
            // Проверка за граници
            if (row >= 0 && row < data.GetLength(0) && col >= 0 && col < data.GetLength(1))
            {
                return data[row, col];
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
        set
        {
            // Проверка за граници
            if (row >= 0 && row < data.GetLength(0) && col >= 0 && col < data.GetLength(1))
            {
                data[row, col] = value;
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
    }
}

Диапазонни индекси (Ranges & Indices)

В C# 8.0 бяха въведени нови типове System.Index и System.Range, които позволяват използването на синтаксис за достъп до елементи от края на колекцията (^) и за получаване на поддиапазон (..). Тези понятия често се наричат "индекси", но се различават от класическите индексиращи.

using System;

public class ArrayExample
{
    public static void Main(string[] args)
    {
        string[] words = { "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog" };

        // Използване на System.Index за достъп от края
        Index last = ^1; // Индекс на последния елемент
        Console.WriteLine(words[last]); // dog

        // Използване на System.Range за получаване на поддиапазон
        Range middle = 1..4; // Елементи с индекси 1 до (но не включително) 4
        string[] subset = words[middle]; // {"quick", "brown", "fox"}

        // Range с използване на System.Index
        Range fromEnd = ^3..; // от трети от края до края
        string[] suffix = words[fromEnd]; // {"the", "lazy", "dog"}
    }
}

Практическо приложение

Активно използвах индексиращите при създаване на собствени класове колекции или обвивки над съществуващи за по-интуитивен достъп до данните. Например:

  • Разработка на класове, представящи матрици или многомерни данни, където достъпът по координати matrix[row, col] е логичен.
  • Създаване на обвивки над Dictionary<> или други колекции, където достъпът по ключ чрез индексатор подобрява четимостта на кода.
  • В прости колекции, където е необходимо синтактично удобство за достъп, подобно на масив.

Диапазонните индекси (System.Index и System.Range) бяха използвани за по-кратък достъп до части от масиви или списъци, което е особено полезно при работа с поднизове или частични данни от колекции.