it-swarm-eu.dev

.NET Properties - Použijte soukromou sadu nebo vlastnost ReadOnly?

V jakých situacích bych měl použít soukromou sadu na vlastnost versus její provedení jako vlastnost ReadOnly? Vezměte v úvahu dva velmi zjednodušující příklady uvedené níže.

První příklad:

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

Druhý příklad:

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

Oba přinášejí stejné výsledky. Je to situace, kdy neexistují správné a špatné věci a je to jen otázka preference?

48
tgxiii

Existuje několik důvodů, proč používat private set.

1) Pokud vůbec nepoužíváte podpůrné pole a chcete automatickou vlastnost jen pro čtení:

public string Name { get; private set; }   

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

2) Pokud chcete dělat další práci, když upravujete proměnnou uvnitř své třídy a chcete ji zachytit na jednom místě:

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

Obecně však jde o osobní preference. Pokud vím, neexistují žádné důvody k použití jednoho nad druhým.

43
Adam Lear

Použijte soukromá sada, pokud chcete k setteru nelze přistupovat zvenčí.

Použijte jen pro čtení, pokud chcete nastavte vlastnost pouze jedno. V konstruktoru nebo inicializátoru proměnné.

TEST TOTO:

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
    }
}
31
asakura89

Mohu navrhnout třetí možnost?

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

Díky tomu je vlastnost Name efektivně čitelná pouze pro všechny vnější kódy a poskytuje explicitní metodu Set. Dávám přednost explicitní sadě než pouhému použití set na vlastnosti Name, protože při nastavení měníte hodnotu. Normálně, pokud nastavíte hodnotu vlastnosti, očekáváte, že dostanete stejnou hodnotu zpět, když zavoláte get později, což by se nestalo, kdybyste udělali ToTitleCase v - set.

Jak jste však uvedli, neexistuje žádná správná odpověď.

9
Dave Wise

Počínaje C # 6.0 byly do jazyka přidány automatické vlastnosti getter. Viz zde: https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#getter-only-auto-properties .

Zde je příklad:

public class SomeClass
{
    public int GetOnlyInt { get; }

    public int GetOnlyIntWithInitializer { get; } = 25;

    public SomeClass(int getOnlyInt)
    {
        GetOnlyInt = getOnlyInt;
    }
}
5
Daniel Neel

Nepoužívejte druhý příklad. Celým bodem používání vlastnosti - i když se nic neděje nad rámec získání getteru a nastavení setteru - je přenést veškerý přístup přes tento getter a setter, takže pokud budete někdy potřebovat změnit chování, bude to vše v jedno místo.

Druhý příklad se vzdává toho, že v případě nastavení vlastnosti. Pokud jste tento přístup použili ve velké, složité třídě a později jste potřebovali změnit chování nemovitosti, měli byste být v zemi, kde se provádí vyhledávání a nahrazování, namísto provedení změny na jednom místě - soukromý setr.

4
Carson63000

Kdykoli jsem potřeboval změnit úroveň přístupu nastavovače, obecně jsem ji změnil buď na Chráněné (pouze tato třída a odvozené třídy mohou změnit hodnotu) nebo přítele (pouze členové mého shromáždění mohou změnit hodnotu).

Používání privátního kódu však dává dokonalý smysl, pokud chcete kromě nastavení hodnoty podkladu provádět další úkoly v nastavení. Jak již bylo zmíněno dříve, je dobré navrhnout, aby vaše referenční hodnoty nebyly přímo odkazovány, ale místo toho k nim přistupovaly pouze prostřednictvím jejich vlastností. Tím je zajištěno, že pozdější změny, které provedete ve vlastnosti, budou použity interně i externě. A prakticky neexistuje výkonnostní sankce za odkazování na vlastnost vs její podpůrnou proměnnou.

2
Prlaba

A prakticky neexistuje výkonnostní pokuta ...

K objasnění je však přístup k vlastnosti is pomalejší než přístup k její proměnné. Getr a setter vlastnosti jsou metody, které vyžadují volání a návrat, zatímco k podkladové proměnné vlastnosti se přistupuje přímo.

To je důvod, proč v případech, kdy je možné získat getr vlastnosti mnohokrát v rámci bloku kódu, je hodnota vlastnosti někdy nejprve uložena do mezipaměti (uložena do lokální proměnné) a místo toho použita lokální proměnná. To samozřejmě předpokládá, že vlastnost nemůže být asynchronně změněna během provádění bloku.

0
Prlaba