Aracılığıyla paylaş


Salt Okunur Örnek Üyeleri

Not

Bu makale bir özellik belirtimidir. Belirtim, özelliğin tasarım belgesi olarak görev alır. Önerilen belirtim değişikliklerini ve özelliğin tasarımı ve geliştirilmesi sırasında gereken bilgileri içerir. Bu makaleler, önerilen belirtim değişiklikleri son haline getirilene ve geçerli ECMA belirtimine dahil edilene kadar yayımlanır.

Özellik belirtimi ile tamamlanan uygulama arasında bazı tutarsızlıklar olabilir. İlgili dil tasarım toplantısı (LDM) notlarında, bu farklılıklar kaydedilir.

Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek içinbelirtimleri makalesinde bulabilirsiniz.

Gündemdeki Sorun: https://github.com/dotnet/csharplang/issues/1710

Özet

Yapının tek tek örnek üyelerinin durumu değiştirmediğini belirtmenin bir yolunu sağlayın; tıpkı readonly struct'ın hiçbir örnek üyenin durumu değiştirmediğini belirttiği gibi.

salt okunur örnek üyesinin != saf örnek üyesiolduğuna dikkat çekmek gerekir. saf örnek üyesi hiçbir durumun değiştirilmeyeceğini garanti eder. readonly örnek üyesi yalnızca örnek durumunun değiştirilmeyeceğini garanti eder.

üzerindeki tüm örnek üyeleri, salt okunur olmayan yapılarda bildirilen açık salt okunur örnek üyeleri örtük olarak salt okunur örnek üyeleri olarak kabul edilebilir. Örneğin, kendisi salt okunur olmayan bir örnek üyesini (geçerli örnekte veya örneğin bir alanında) çağırdıysanız, yine de gizli kopyalar oluştururlar.

Motivasyon

C# 8.0'ın öncesinde kullanıcılar, derleyicinin tüm alanların salt okunur olmasını zorunlu kıldığı (ve uzantıya göre hiçbir örnek üyesinin durumu değiştirmediği) readonly struct türleri oluşturabilir. Ancak, erişilebilir alanları açığa çıkaran veya değiştirilebilir ve değiştirilemez üyelerin karışımına sahip mevcut bir API'niz olduğu bazı senaryolar vardır. Bu koşullar altında, türü readonly olarak işaretleyemezsiniz (hataya neden olan bir değişiklik olacaktır).

Bunun normalde in parametreleri dışında çok fazla etkisi olmaz. Salt okunur olmayan yapılar için in parametreleri ile, derleyici, çağrının iç durumu değiştirmediğini garanti edemediği için her örnek üyesi çağrısı için parametrenin bir kopyasını oluşturur. Bu, çok sayıda kopyaya ve yapıyı doğrudan değere göre geçirmiş olmanızdan daha kötü bir genel performansa yol açabilir. Örneğin, keskin bu koda bakın

Gizli kopyaların oluşabileceği diğer senaryolar arasında static readonly alanları ve değişmez değerleribulunmaktadır. Gelecekte destekleniyorsa, kesilebilir sabitler aynı teknede sonuçlanacaktır; yapısı readonlyolarak işaretlenmemişse, hepsi şu anda tam bir kopya (örnek üye çağrısı) gerektirir.

Tasarım

Kullanıcının bir örnek üyesinin kendisi readonly olduğunu ve örneğin durumunu değiştirmediğini belirtmesine izin verin (derleyici tarafından yapılan tüm uygun doğrulamalar ile elbette). Mesela:

public struct Vector2
{
    public float x;
    public float y;

    public readonly float GetLengthReadonly()
    {
        return MathF.Sqrt(LengthSquared);
    }

    public float GetLength()
    {
        return MathF.Sqrt(LengthSquared);
    }

    public readonly float GetLengthIllegal()
    {
        var tmp = MathF.Sqrt(LengthSquared);

        x = tmp;    // Compiler error, cannot write x
        y = tmp;    // Compiler error, cannot write y

        return tmp;
    }

    public readonly float LengthSquared
    {
        get
        {
            return (x * x) +
                   (y * y);
        }
    }
}

public static class MyClass
{
    public static float ExistingBehavior(in Vector2 vector)
    {
        // This code causes a hidden copy, the compiler effectively emits:
        //    var tmpVector = vector;
        //    return tmpVector.GetLength();
        //
        // This is done because the compiler doesn't know that `GetLength()`
        // won't mutate `vector`.

        return vector.GetLength();
    }

    public static float ReadonlyBehavior(in Vector2 vector)
    {
        // This code is emitted exactly as listed. There are no hidden
        // copies as the `readonly` modifier indicates that the method
        // won't mutate `vector`.

        return vector.GetLengthReadonly();
    }
}

Özellik erişimcilerine salt okunur, erişimcide this'ın değiştirilmediğini belirtmek için uygulanabilir. Bu erişimciler üye alanının durumunu değiştirdiğinden ancak bu üye alanının değerini değiştirmediğinden, aşağıdaki örneklerde salt okunur ayarlayıcılar vardır.

public readonly int Prop1
{
    get
    {
        return this._store["Prop1"];
    }
    set
    {
        this._store["Prop1"] = value;
    }
}

Özellik söz dizimine readonly uygulandığında, bu, tüm erişimcilerin readonlyolduğu anlamına gelir.

public readonly int Prop2
{
    get
    {
        return this._store["Prop2"];
    }
    set
    {
        this._store["Prop2"] = value;
    }
}

Salt okunur, yalnızca içeren türü değiştirmeyen erişimcilere uygulanabilir.

public int Prop3
{
    readonly get
    {
        return this._prop3;
    }
    set
    {
        this._prop3 = value;
    }
}

Otomatik özelliklerin bazılarına salt okunur olarak uygulanabilir, ancak bunun anlamlı bir etkisi olmaz. Derleyici, otomatik gerçekleştirilen tüm get işlevlerini readonly anahtar sözcüğü bulunsa da bulunmasa da salt okunur olarak değerlendirir.

// Allowed
public readonly int Prop4 { get; }
public int Prop5 { readonly get; set; }

// Not allowed
public int Prop6 { readonly get; }
public readonly int Prop7 { get; set; }
public int Prop8 { get; readonly set; }

Salt okunur, el ile uygulanan olaylara uygulanabilir, ancak alan benzeri olaylara uygulanamaz. Tek tek olay işleyicisi erişimcilerine salt okunur olarak uygulanamaz (ekleme/kaldırma).

// Allowed
public readonly event Action<EventArgs> Event1
{
    add { }
    remove { }
}

// Not allowed
public readonly event Action<EventArgs> Event2;
public event Action<EventArgs> Event3
{
    readonly add { }
    readonly remove { }
}
public static readonly event Event4
{
    add { }
    remove { }
}

Diğer bazı söz dizimi örnekleri:

  • İfade gövdeli üyeler: public readonly float ExpressionBodiedMember => (x * x) + (y * y);
  • Genel kısıtlamalar: public readonly void GenericMethod<T>(T value) where T : struct { }

Derleyici her zamanki gibi örnek üyesini yayar ve ayrıca örnek üyesinin durumu değiştirmediğini belirten derleyici tarafından tanınan bir öznitelik de yayar. Bu, gizli this parametresinin ref Tyerine in T olmasına neden olur.

Bu, kullanıcının derleyicinin bir kopya oluşturmasına gerek kalmadan söz konusu örnek yöntemini güvenli bir şekilde çağırmasına olanak tanır.

Kısıtlamalar şunlardır:

  • readonly değiştirici statik yöntemlere, oluşturuculara veya yıkıcılara uygulanamaz.
  • readonly değiştirici temsilcilere uygulanamaz.
  • readonly değiştiricisi sınıf veya arabirimin üyelerine uygulanamaz.

Dezavantaj -ları

Bugün readonly struct yöntemlerinde olduğu gibi aynı dezavantajlar. Bazı kodlar yine de gizli kopyalara neden olabilir.

Notlar

Bir özniteliği veya başka bir anahtar sözcüğü kullanmak da mümkün olabilir.

Bu teklif, her ikisi de mevcut tekliflere sahip olan functional purity ve/veya constant expressionsile ilgilidir (ancak daha çok bir alt kümesidir).