.NET Özellikleri - Özel Set veya ReadOnly Property Kullanılsın mı?


45

Hangi durumda bir mülkiyeti üzerinde bir Özel Küme kullanmalıyım ki onu bir ReadOnly mülkü yapmalıyım? Aşağıdaki çok basit iki örneği göz önünde bulundurun.

İlk örnek:

Public Class Person

    Private _name As String

    Public Property Name As String
        Get
            Return _name
        End Get
        Private Set(ByVal value As String)
            _name = value
        End Set
    End Property

    Public Sub WorkOnName()

        Dim txtInfo As TextInfo = _
            Threading.Thread.CurrentThread.CurrentCulture.TextInfo

        Me.Name = txtInfo.ToTitleCase(Me.Name)

    End Sub

End Class

// ----------

public class Person
{
    private string _name;
    public string Name
    {
        get { return _name; }
        private set { _name = value; }
    }

    public void WorkOnName()
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        this.Name = txtInfo.ToTitleCase(this.Name);
    }
}

İkinci örnek:

Public Class AnotherPerson

    Private _name As String

    Public ReadOnly Property Name As String
        Get
            Return _name
        End Get
    End Property

    Public Sub WorkOnName()

        Dim txtInfo As TextInfo = _
            Threading.Thread.CurrentThread.CurrentCulture.TextInfo

        _name = txtInfo.ToTitleCase(_name)

    End Sub

End Class

// ---------------

public class AnotherPerson
{
    private string _name;
    public string Name
    {
        get { return _name; }
    }

    public void WorkOnName()
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        _name = txtInfo.ToTitleCase(_name);
    }
}

Her ikisi de aynı sonuçları verir. Bu, doğru ya da yanlış olmayan bir durum mu ve sadece bir tercih meselesi mi?


public string Name { get; protected set; }miras yoluyla.
samis

Yanıtlar:


42

Kullanmanın birkaç nedeni var private set.

1) Bir yedekleme alanı hiç kullanmıyorsanız ve salt okunur bir otomatik özellik istiyorsanız:

public string Name { get; private set; }   

public void WorkOnName()
{
    TextInfo txtInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
    Name = txtInfo.ToTitleCase(Name);
}  

2) Sınıfınızdaki değişkeni değiştirirken fazladan çalışmak ve bunu tek bir yerde yakalamak istiyorsanız:

private string _name = string.Empty;
public string Name 
{ 
    get { return _name; }
    private set 
    {
        TextInfo txtInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
        _name = txtInfo.ToTitleCase(value);
    }
}

Genel olarak, yine de, kişisel tercih meselesi. Bildiğim kadarıyla, birini diğerine kullanmak için performans nedenleri yok.


1
Sadece bunu da ekledim çünkü soruda vb.net etiketi de var, ama vb.net'te ya almak ya da ayarlamak için özel kullanıyorsanız bir destek belirtmeniz gerekiyor. Öyleyse, vb.net'te, özelliği salt okunur yapmak için daha az iş olduğunu düşünüyorum.
user643192

Bunu asla bilemedim private set. :-)
Afzaal Ahmad Zeeshan 12:14

9
2016 C # 6.0 Söz konusu yanıtı okuyanlar için bir güncelleme bir destek alanı olmadan bir Salt okunur özelliği için izin salt okunur otomatik özellikleri tanıttı: public string Name { get; }. Değiştirilebilir bir özellik istemiyorsanız, şimdi tercih edilen sözdizimi budur.
Alexey,

4
Kullanmamak için çok iyi bir sebep private set, onun iddia ettiğimiz kadar değişmez olmasıdır. Gerçekten değişmez bir sınıf uygulamak istiyorsanız, salt okunur bir zorunluluktur.
RubberDuck

Salt okunur KULLANMAMANIZ bir performans nedeni olabilir. Salt okunur bir yapı alanı yöntemlerine erişirken yapıların gereksiz şekilde kopyalanmasına neden gibi görünüyor. codeblog.jonskeet.uk/2014/07/16/…
Triynko

28

Kullanım özel set istediğiniz zaman ayarlayıcı dışarıdan erişilemez .

Özelliği yalnızca bir kez ayarlamak istediğinizde salt okunur kullanın . Yapıcı veya değişken başlatıcıda.

BU TEST:

void Main()
{
    Configuration config = new Configuration();
    config.ResetConfiguration();

    ConfigurationReadOnly configRO = new ConfigurationReadOnly();
    configRO.ResetConfiguration();
}

public class Configuration
{
    public Color BackgroundColor { get; private set; }
    public Color ForegroundColor { get; private set; }
    public String Text { get; private set; }

    public Configuration()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }

    public void ResetConfiguration()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }
}

public class ConfigurationReadOnly
{
    public readonly Color BackgroundColor;
    public readonly Color ForegroundColor;
    public readonly String Text;

    public ConfigurationReadOnly()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }

    public void ResetConfiguration()
    {
        BackgroundColor = Color.Black; // compile error: due to readonly keyword
        ForegroundColor = Color.White; // compile error: due to readonly keyword
        Text = String.Empty; // compile error: due to readonly keyword
    }
}

Cevabınızı kabul ederken, örneğinizde bazı iyileştirmeler yapılabilir. Derleyici hatasının ortaya çıkacağı bir yorum yapmak isteyebilirsiniz.
Michael Richardson

NB C # readonlyanahtar sözcüğüne karşılık gelen VB.NET sözdizimi ReadOnly, özellik yerine alana uygulanır .
Zev Spitz

8

Üçüncü bir seçenek önerebilir miyim?

public class Person
{
    public string Name { get; protected set; }

    public void SetName(string name)
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        this.Name = txtInfo.ToTitleCase(name);
    }
}

Bu, Name özelliğini etkin bir şekilde Salt Okunur dışındaki tüm kodlara okutur ve açık bir Set yöntemi sağlar. Ben sadece kullanmak yerine açık Set tercih kümesi bunu ayarlarken değerini değiştirerek, çünkü adı mülkiyet. Eğer Normalde set bir özellik değeri, sen Aradığınızda aynı değeri geri almak için beklemek get daki ToTitleCase yapsam olur olmaz, hangi sonradan sette .

Ancak, dediğiniz gibi, doğru bir cevap yok.


'Özel kümenin' derleyicide özel bir anlam ifade ettiğine inanıyorum (sadece özel bir erişimci olarak değil). Bu aynı zamanda korumalı sette durum mu? Olmazsa, özel kümenin özel semantiği varsa, korumalı kümenin semantik eşdeğeri nerede? Bunu açıklayan herhangi bir belge bulamadım.
Sprague

1
+1 ancak "SetName" yerine "Rename" yöntemini çağırırım.
MattDavey


4

İkinci örneği kullanmayın. Bir özelliği kullanmanın tüm amacı - alıcı ve ayarlayıcı ayarlarının ötesinde hiçbir şey olmasa bile - gelecekte alıcı davranışını değiştirmek zorunda kalırsanız, alıcı ve ayarlayıcı aracılığıyla tüm erişimi hizalamaktır. bir yer.

İkinci örneğiniz özelliği ayarlamak durumunda bunu iptal eder. Bu yaklaşımı geniş, karmaşık bir sınıfta kullandıysanız ve daha sonra mülkün davranışını değiştirmeye ihtiyaç duyduysanız, değişikliği tek bir yerde - özel ayarlayıcıda yapmak yerine - ara ve değiştir - in yerinde olursunuz.


2

Bir ayarlayıcının erişim seviyesini ne zaman değiştirmem gerektiğine, genellikle onu Korumalı (yalnızca bu sınıf ve türetilmiş sınıflar değeri değiştirebilir) veya Arkadaş olarak değiştirdim (yalnızca montajımın üyeleri değeri değiştirebilir).

Ancak Özel'i kullanmak, destekçiyi değiştirmenin yanı sıra, ayarlayıcıda diğer görevleri yapmak istediğinizde de mantıklı gelir. Daha önce de belirtildiği gibi, destekleme değerlerine doğrudan referans vermemek yerine, sadece özelliklerine erişebilmek iyi bir tasarımdır. Bu özellik, daha sonra bir özellik üzerinde yaptığınız değişikliklerin hem dahili hem de harici olarak uygulanmasını sağlar. Ayrıca, bir özelliği referans değişkenine karşı destekleme değişkenine göre performansta neredeyse hiçbir ceza yoktur.


0

Ve neredeyse hiçbir performans cezası yok ...

Ama açıklığa kavuşturmak için, bir özellik erişme olduğunu onun arka değişkeni erişen daha yavaş. Bir mülkün alıcısı ve ayarlayıcısı, Arama ve Geri Dönüş gerektiren yöntemlerdir, oysa mülkün destek değişkenine doğrudan erişilir.

Bu nedenle, bir mülkün alıcısının bir kod bloğu içinde birçok kez erişilebildiği durumlarda, mülkün değeri bazen önce önbelleğe alınır (yerel değişkene kaydedilir) ve bunun yerine yerel değişken kullanılır. Tabii ki, bu blok yürütülürken özellik zaman uyumsuz olarak değiştirilemez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.