Sobes.tech
Junior

Ce sunt indicii în C#? Ce tipuri de indici există și le-ați folosit în practică?

sobes.tech AI

Răspuns de la AI

Indexatorii în C# permit accesul la o instanță a unei clase sau structuri ca la un array, folosind sintaxa []. Nu sunt statici și suprascriu operatorul [].

Indexatori

Indexatorii permit definirea logicii de acces la elementele unei colecții sau structuri de date în interiorul unei clase.

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

    // Indexator care permite obținerea sau setarea unui element după index
    public string this[int index]
    {
        get
        {
            // Verificare limite
            if (index >= 0 && index < data.Length)
            {
                return data[index];
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
        set
        {
            // Verificare limite
            if (index >= 0 && index < data.Length)
            {
                data[index] = value;
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
    }
}

Tipuri de parametri pentru indexatori

Indexatorii pot accepta orice număr de parametri de orice tip, nu doar tipuri întregi.

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

    // Indexator cu parametru de tip string
    public string this[string key]
    {
        get
        {
            if (_dictionary.ContainsKey(key))
            {
                return _dictionary[key];
            }
            else
            {
                return null; // Sau arunca o excepție
            }
        }
        set
        {
            _dictionary[key] = value;
        }
    }
}

Suprasarcina indexatorilor

Se pot crea indexatori suprasaturați cu semnături diferite (seturi de parametri și tipuri).

public class Matrix
{
    private int[,] data;

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

    // Indexator cu doi parametri întregi
    public int this[int row, int col]
    {
        get
        {
            // Verificare limite
            if (row >= 0 && row < data.GetLength(0) && col >= 0 && col < data.GetLength(1))
            {
                return data[row, col];
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
        set
        {
            // Verificare limite
            if (row >= 0 && row < data.GetLength(0) && col >= 0 && col < data.GetLength(1))
            {
                data[row, col] = value;
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
    }
}

Indici de interval (Ranges & Indices)

În C# 8.0 au fost introduse noile tipuri System.Index și System.Range, care permit utilizarea sintaxei pentru accesarea elementelor de la sfârșitul colecției (^) și pentru obținerea unui subinterval (..). Aceste concepte sunt adesea numite "indecși", dar diferă de indexatorii clasici.

using System;

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

        // Utilizarea System.Index pentru acces de la sfârșit
        Index last = ^1; // indexul ultimului element
        Console.WriteLine(words[last]); // dog

        // Utilizarea System.Range pentru obținerea unui subinterval
        Range middle = 1..4; // elemente de la indexul 1 până la (dar fără a include) indexul 4
        string[] subset = words[middle]; // {"quick", "brown", "fox"}

        // Range cu System.Index
        Range fromEnd = ^3..; // de la al treilea de la sfârșit până la sfârșit
        string[] suffix = words[fromEnd]; // {"the", "lazy", "dog"}
    }
}

Aplicare practică

Am folosit activ indexatorii la crearea propriilor clase de colecții sau învelișuri peste colecții existente pentru a oferi acces mai intuitiv la date. De exemplu:

  • Dezvoltarea claselor care reprezintă matrici sau date multidimensionale, unde accesul după coordonate matrix[row, col] era logic.
  • Crearea de învelișuri peste Dictionary<> sau alte colecții, unde accesul după cheie prin indexator îmbunătățește lizibilitatea codului.
  • În colecții simple, unde era necesar un acces sintactic convenabil, similar cu array-urile.

Indici de interval (System.Index și System.Range) au fost folosiți pentru acces mai concis la părți din array-uri sau liste, fiind deosebit de utili la lucrul cu subșiruri sau date parțiale din colecție.