Sobes.tech
Junior

Co jsou indexy v C#? Jaké typy indexů existují a používal jste je v praxi?

sobes.tech AI

Odpověď od AI

Indexery v C# umožňují přístup k instanci třídy nebo struktury jako k poli pomocí syntaxe []. Nejsou statické a přetěžují operátor [].

Indexery

Indexery umožňují definovat logiku přístupu k prvkům kolekce nebo datové struktury uvnitř třídy.

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

    // Indexer umožňující získat nebo nastavit prvek podle indexu
    public string this[int index]
    {
        get
        {
            // Kontrola hranic
            if (index >= 0 && index < data.Length)
            {
                return data[index];
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
        set
        {
            // Kontrola hranic
            if (index >= 0 && index < data.Length)
            {
                data[index] = value;
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
    }
}

Typy parametrů indexerů

Indexery mohou přijímat libovolné množství parametrů jakéhokoliv typu, nikoliv pouze celočíselné.

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

    // Indexer s parametrem typu string
    public string this[string key]
    {
        get
        {
            if (_dictionary.ContainsKey(key))
            {
                return _dictionary[key];
            }
            else
            {
                return null; // nebo vyvolat výjimku
            }
        }
        set
        {
            _dictionary[key] = value;
        }
    }
}

Přetížení indexerů

Lze vytvářet přetížené indexery s různými signaturami (sady a typy parametrů).

public class Matrix
{
    private int[,] data;

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

    // Indexer se dvěma celočíselnými parametry
    public int this[int row, int col]
    {
        get
        {
            // Kontrola hranic
            if (row >= 0 && row < data.GetLength(0) && col >= 0 && col < data.GetLength(1))
            {
                return data[row, col];
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
        set
        {
            // Kontrola hranic
            if (row >= 0 && row < data.GetLength(0) && col >= 0 && col < data.GetLength(1))
            {
                data[row, col] = value;
            }
            else
            {
                throw new IndexOutOfRangeException();
            }
        }
    }
}

Rozsahy indexů (Ranges & Indices)

V C# 8.0 byly zavedeny nové typy System.Index a System.Range, které umožňují používat syntax pro přístup k prvkům od konce kolekce (^) a pro získání podmnožiny (..). Tyto pojmy jsou často označovány jako "indexy", ale liší se od klasických indexátorů.

using System;

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

        // Použití System.Index pro přístup od konce
        Index last = ^1; // index posledního prvku
        Console.WriteLine(words[last]); // dog

        // Použití System.Range pro získání podmnožiny
        Range middle = 1..4; // prvky od indexu 1 do (ale nevčetně) indexu 4
        string[] subset = words[middle]; // {"quick", "brown", "fox"}

        // Range s použitím System.Index
        Range fromEnd = ^3..; // od třetího od konce do konce
        string[] suffix = words[fromEnd]; // {"the", "lazy", "dog"}
    }
}

Praktické použití

Aktivně jsem používal indexery při tvorbě vlastních tříd kolekcí nebo obalů nad existujícími kolekcemi pro poskytnutí intuitivnějšího přístupu k datům. Například:

  • Vývoj tříd reprezentujících matice nebo vícerozměrná data, kde byl přístup podle souřadnic matrix[row, col] logický.
  • Vytváření obalů nad Dictionary<> nebo jinými kolekcemi, kde přístup podle klíče přes indexer zlepšoval čitelnost kódu.
  • V jednoduchých kolekcích, kde bylo potřeba syntakticky pohodlný přístup, podobně jako u pole.

Používal jsem rozsahové indexy (System.Index a System.Range) pro stručnější přístup k částem polí nebo seznamů, což je zvláště užitečné při práci s podřetězci nebo částečnými daty z kolekce.