Megosztás a következőn keresztül:


Indexelők használata (C# programozási útmutató)

Az indexelők olyan szintaktikai kényelmi funkciók, amelyek lehetővé teszik egy osztály, struktúra vagy felület létrehozását, amelyet az ügyfélalkalmazások tömbként érhetnek el. A fordító létrehoz egy tulajdonságot Item (vagy egy másik néven elnevezett tulajdonságot, ha IndexerNameAttribute van) és a megfelelő kiegészítő módszereket. Az indexelőket leggyakrabban olyan típusokban implementálják, amelyek elsődleges célja egy belső gyűjtemény vagy tömb beágyazása. Tegyük fel például, hogy van egy osztálya TempRecord , amely a Fahrenheitben mért hőmérsékletet 10 különböző időpontban rögzíti egy 24 órás időszakban. Az osztály egy típustömböt temps float[] tartalmaz a hőmérsékleti értékek tárolásához. Az indexelő ebben az osztályban történő implementálásával az ügyfelek a példány hőmérsékletét TempRecord ahelyett, hogy float temp = tempRecord[4] a következőképpen float temp = tempRecord.temps[4]érik el. Az indexelő jelölése nem csak az ügyfélalkalmazások szintaxisát egyszerűsíti; az osztályt és célját is intuitívabbá teszi más fejlesztők számára.

Ha indexelőt szeretne deklarálni egy osztályon vagy szerkezeten, használja ezt a kulcsszót az alábbi példában látható módon:

// Indexer declaration
public int this[int index]
{
    // get and set accessors
}

Fontos

Az indexelő deklarálása automatikusan létrehoz egy, az objektumon elnevezett Item tulajdonságot. A Item tulajdonság közvetlenül nem érhető el a példánytag hozzáférési kifejezéséből. Emellett ha saját Item tulajdonságot ad hozzá egy indexelővel rendelkező objektumhoz, cs0102 fordítóhiba jelenik meg. A hiba elkerülése érdekében használja az IndexerNameAttribute indexelő átnevezését a cikk későbbi részében részletezett módon.

Megjegyzések

Az indexelő típusának és paramétereinek legalább olyan hozzáférhetőnek kell lenniük, mint maga az indexelő. További információ az akadálymentességi szintekről: Access Modifiers.

További információ az indexelők felülettel való használatáról: Interfészindexelők.

Az indexelő aláírása a formális paraméterek számából és típusaiból áll. Nem tartalmazza az indexelő típusát vagy a formális paraméterek nevét. Ha ugyanabban az osztályban egynél több indexelőt deklarál, azoknak eltérő aláírásokkal kell rendelkezniük.

Az indexelők nem tartoznak változók közé; ezért az indexelő értéke hivatkozással (vagy out paraméterkéntref) nem adható át, kivéve, ha az értéke hivatkozás (azaz hivatkozással adja vissza).)

Ha az indexelőnek olyan nevet szeretne adni, amelyet más nyelvek is használhatnak, használja System.Runtime.CompilerServices.IndexerNameAttributeaz alábbi példában látható módon:

// Indexer declaration
[System.Runtime.CompilerServices.IndexerName("TheItem")]
public int this[int index]
{
    // get and set accessors
}

Ennek az indexelőnek a neve TheItemvan, mivel az indexelő névattribútuma felülbírálta. Alapértelmezés szerint az indexelő neve .Item

1. példa

Az alábbi példa bemutatja, tempshogyan deklarálhat egy privát tömbmezőt és egy indexelőt. Az indexelő lehetővé teszi a példány tempRecord[i]közvetlen elérését. Az indexelőt úgy is használhatja, hogy nyilvános tagként deklarálja a tömböt, tempRecord.temps[i]és közvetlenül hozzáfér a tagjaihoz.

public class TempRecord
{
    // Array of temperature values
    float[] temps =
    [
        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 => temps.Length;
    
    // Indexer declaration.
    // If index is out of range, the temps array will throw the exception.
    public float this[int index]
    {
        get => temps[index];
        set => temps[index] = value;
    }
}

Figyelje meg, hogy amikor egy indexelő hozzáférését kiértékeli, például egy Console.Write utasításban, a lekéréses kiegészítő meghívása történik. Ezért, ha nincs get tartozék, fordítási időhiba lép fel.

var 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++)
{
    Console.WriteLine($"Element #{i} = {tempRecord[i]}");
}

Indexelés más értékekkel

A C# nem korlátozza az indexelő paraméter típusát egész számra. Hasznos lehet például egy sztring indexelővel való használata. Az ilyen indexelők a gyűjtemény sztringjének keresésével és a megfelelő érték visszaadásával implementálhatók. Mivel a tartozékok túlterhelhetők, a sztring- és egész számverziók együtt létezhetnek.

2. példa

Az alábbi példa egy olyan osztályt deklarál, amely a hét napjait tárolja. A get kiegészítő egy sztringet, egy nap nevét veszi fel, és visszaadja a megfelelő egész számot. A "Vasárnap" például 0, a "Hétfő" pedig 1 értéket ad vissza, és így tovább.

// Using a string as an indexer value
class DayCollection
{
    string[] days = ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"];

    // Indexer with only a get accessor with the expression-bodied definition:
    public int this[string day] => FindDayIndex(day);

    private int FindDayIndex(string day)
    {
        for (int j = 0; j < days.Length; j++)
        {
            if (days[j] == day)
            {
                return j;
            }
        }

        throw new ArgumentOutOfRangeException(
            nameof(day),
            $"Day {day} is not supported.\nDay input must be in the form \"Sun\", \"Mon\", etc");
    }
}

2. példa felhasználása

var week = new DayCollection();
Console.WriteLine(week["Fri"]);

try
{
    Console.WriteLine(week["Made-up day"]);
}
catch (ArgumentOutOfRangeException e)
{
    Console.WriteLine($"Not supported input: {e.Message}");
}

3. példa

Az alábbi példa egy osztályt deklarál, amely a hét napjait tárolja az System.DayOfWeek enumerálás használatával. A get kiegészítő egy DayOfWeeknap értékét veszi figyelembe, és a megfelelő egész számot adja vissza. Például DayOfWeek.Sunday 0 értéket ad vissza, DayOfWeek.Monday 1-et és így tovább.

using Day = System.DayOfWeek;

class DayOfWeekCollection
{
    Day[] days =
    [
        Day.Sunday, Day.Monday, Day.Tuesday, Day.Wednesday,
        Day.Thursday, Day.Friday, Day.Saturday
    ];

    // Indexer with only a get accessor with the expression-bodied definition:
    public int this[Day day] => FindDayIndex(day);

    private int FindDayIndex(Day day)
    {
        for (int j = 0; j < days.Length; j++)
        {
            if (days[j] == day)
            {
                return j;
            }
        }
        throw new ArgumentOutOfRangeException(
            nameof(day),
            $"Day {day} is not supported.\nDay input must be a defined System.DayOfWeek value.");
    }
}

3. példa felhasználása

var week = new DayOfWeekCollection();
Console.WriteLine(week[DayOfWeek.Friday]);

try
{
    Console.WriteLine(week[(DayOfWeek)43]);
}
catch (ArgumentOutOfRangeException e)
{
    Console.WriteLine($"Not supported input: {e.Message}");
}

Robusztus programozás

Az indexelők biztonságának és megbízhatóságának két fő módja van:

  • Ügyeljen arra, hogy valamilyen hibakezelési stratégiát használjon annak érdekében, hogy az ügyfélkód érvénytelen indexértéken haladjon át. A cikk korábbi első példájában a TempRecord osztály egy Length tulajdonságot biztosít, amely lehetővé teszi, hogy az ügyfélkód ellenőrizze a bemenetet, mielőtt átadja azt az indexelőnek. A hibakezelő kódot magában az indexelőben is elhelyezheti. Mindenképpen dokumentálja a felhasználók számára az indexelő tartozékon belüli kivételeket.

  • Állítsa be a be- és beszerelt tartozékok akadálymentességét az ésszerűnek megfelelő korlátozó értékre. Ez különösen a set tartozék szempontjából fontos. További információ: A kiegészítő akadálymentesség korlátozása.

Lásd még