Dizin oluşturucuları kullanma (C# Programlama Kılavuzu)

Dizinleyiciler, istemci uygulamalarının dizi olarak erişebileceği bir sınıf, yapı veya arabirim oluşturmanıza olanak tanıyan sözdizimsel bir kolaylıktır. Derleyici bir Item özelliği (ve IndexerNameAttribute varsa alternatif adlandırılmış bir özelliği) ve uygun erişim yöntemlerini oluşturur. Dizin oluşturucular en sık, birincil amacı bir iç koleksiyonu veya diziyi kapsüllemek olan türlerde uygulanır. Örneğin, 24 saatlik bir süre boyunca 10 farklı zamanda kaydedildiği gibi Fahrenheit'teki sıcaklığı temsil eden bir sınıfınız TempRecord olduğunu varsayalım. sınıfı, sıcaklık değerlerini depolamak için bir temps tür float[] dizisi içerir. İstemciler, bu sınıfta bir dizin oluşturucu uygulayarak TempRecord örneğindeki sıcaklıklara float temp = tempRecord[4] olarak değil, float temp = tempRecord.temps[4] olarak erişebilir. İndeksleyici gösterimi yalnızca istemci uygulamaları için söz dizimini basitleştirmekle kalmaz, aynı zamanda sınıfı ve amacını diğer geliştiricilerin daha sezgisel bir şekilde anlamasını sağlar.

Bir sınıf veya yapıda dizin oluşturucu bildirmek için aşağıdaki örnekte gösterildiği gibi bu anahtar sözcüğü kullanın:

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

Önemli

Dizin oluşturucu bildirilmesi, nesne üzerinde adı Item olan bir özelliği otomatik olarak oluşturur. Özelliğine Item örnek üye erişim ifadesinden doğrudan erişilemez. Ayrıca, dizin oluşturuculu bir nesneye kendi Item özelliğinizi eklerseniz CS0102 derleyici hatası alırsınız. Bu hatayı önlemek için, bu makalenin devamında açıklandığı gibi indeksleyiciyi yeniden adlandırın.

Açıklamalar

Dizin oluşturucunun türü ve parametrelerinin türü en az dizin oluşturucunun kendisi kadar erişilebilir olmalıdır. Erişilebilirlik düzeyleri hakkında daha fazla bilgi için bkz . Erişim Değiştiricileri.

Dizin oluşturucuları bir arabirimle kullanma hakkında daha fazla bilgi için bkz . Arabirim Dizin Oluşturucuları.

Dizin oluşturucunun imzası, resmi parametrelerinin sayısından ve türlerinden oluşur. Dizin oluşturucu türünü veya resmi parametrelerin adlarını içermez. Aynı sınıfta birden fazla dizin oluşturucu bildirirseniz, bunların farklı imzaları olmalıdır.

Dizin oluşturucu bir değişken olarak sınıflandırılmaz; bu nedenle, bir dizin oluşturucu değeri bir başvuru olmadıkça (ref veya out parametresi olarak) referansla geçirilemez (yani, referansla döndürülür).

Dizin oluşturucuya diğer dillerin kullanabileceği bir ad sağlamak için, aşağıdaki örnekte gösterildiği gibi kullanın System.Runtime.CompilerServices.IndexerNameAttribute:

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

Bu dizin oluşturucu, TheItem özniteliği tarafından geçersiz kılındığı için bu adla tanımlanır. Dizin oluşturucu adı varsayılan olarak şeklindedir Item.

Örnek 1

Aşağıdaki örnekte, özel dizi alanı, temps ve bir dizinleyici bildirmenin nasıl yapılacağı gösterilmektedir. Dizin oluşturucu, örneğine tempRecord[i]doğrudan erişimi etkinleştirir. Dizin oluşturucuyu kullanmanın alternatifi, diziyi genel üye olarak bildirmek ve üyelerine tempRecord.temps[i]doğrudan erişmektir.

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;
    }
}

Bir dizinleyicinin erişimi değerlendirildiğinde, örneğin bir Console.Write ifadesinde, get erişicisinin çağrıldığına dikkat edin. Bu nedenle, bir get erişimci yoksa, derleme zamanında bir hata oluşur.

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]}");
}

Diğer değerleri kullanarak dizin oluşturma

C# dizin oluşturucu parametre türünü tamsayı ile sınırlamaz. Örneğin, bir indeksleyici ile string kullanmak yararlı olabilir. Böyle bir dizin oluşturucu, koleksiyondaki dize aranarak ve uygun değer döndürülerek uygulanabilir. Erişimciler aşırı yüklenebildiği için, dize ve tamsayı versiyonları birlikte var olabilir.

Örnek 2

Aşağıdaki örnek, haftanın günlerini depolayan bir sınıf bildirir. Bir get erişimci, bir günün adını içeren bir string alır ve karşılık gelen tamsayıyı döndürür. Örneğin, "Pazar" 0 döndürür, "Pazartesi" 1 döndürür ve bu şekilde devam eder.

// 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");
    }
}

Tüketim örneği 2

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}");
}

Örnek 3

Aşağıdaki örnek, sabit listesi kullanarak System.DayOfWeek haftanın günlerini depolayan bir sınıf bildirir. Erişimci get , bir DayOfWeekgünün değerini alır ve karşılık gelen tamsayıyı döndürür. Örneğin, DayOfWeek.Sunday 0 döndürür, DayOfWeek.Monday 1 döndürür, vb.

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.");
    }
}

Kullanım örneği 3

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}");
}

Sağlam programlama

Dizin oluşturucuların güvenliğini ve güvenilirliğini geliştirmenin iki ana yolu vardır:

  • İstemci kodunun geçersiz bir dizin değeri geçirme olasılığını işlemek için bir tür hata işleme stratejisi eklediğinizden emin olun. Bu makalenin önceki bölümlerindeki ilk örnekte TempRecord sınıfı, istemci kodunun girişi dizin oluşturucuya geçirmeden önce doğrulamasını sağlayan bir Length özelliği sağlar. Hata işleme kodunu dizin oluşturucunun içine de yerleştirebilirsiniz. Dizin oluşturucu erişimcisinde oluşturduğunuz herhangi bir özel durumu kullanıcılar için belgelediğinizden emin olun.

  • Get ve set erişimcilerinin erişilebilirliğini, makul olduğu kadar kısıtlayıcı olacak şekilde ayarlayın. Bu özellikle aksesuar için set önemlidir. Daha fazla bilgi için Erişimci Erişilebilirliğini Kısıtlama bölümüne bakın.

Ayrıca bkz.