Wann sollten die Eigenschaften Readonly und Get only verwendet werden?

100

Wann sollte ich in einer .NET-Anwendung die Eigenschaften "ReadOnly" verwenden und wann sollte ich nur "Get" verwenden? Was ist der Unterschied zwischen diesen beiden.

private readonly double Fuel= 0;

public double FuelConsumption
{
    get
    {
        return Fuel;
    }
}        

oder

private double Fuel= 0;

public double FuelConsumption
{
     get
     {
          return Fuel;
     }
}
RAM
quelle
12
für C #> 5 kann die get-Eigenschaft aufpublic double FuelConsumption => Fuel;
meJustAndrew

Antworten:

121

Wenn Sie eine Eigenschaft nur mit einem Getter erstellen, ist Ihre Eigenschaft für jeden Code außerhalb der Klasse schreibgeschützt.

Sie können den Wert jedoch mithilfe der von Ihrer Klasse bereitgestellten Methoden ändern:

public class FuelConsumption {
    private double fuel;
    public double Fuel
    {
        get { return this.fuel; }
    }
    public void FillFuelTank(double amount)
    {
        this.fuel += amount;
    }
}

public static void Main()
{
    FuelConsumption f = new FuelConsumption();

    double a;
    a = f.Fuel; // Will work
    f.Fuel = a; // Does not compile

    f.FillFuelTank(10); // Value is changed from the method's code
}

Wenn Sie das private Feld Ihrer Klasse so readonlyeinstellen, dass Sie den Feldwert nur einmal festlegen können (mithilfe einer Inline-Zuweisung oder im Klassenkonstruktor). Sie können es später nicht mehr ändern.

public class ReadOnlyFields {
    private readonly double a = 2.0;
    private readonly double b;

    public ReadOnlyFields()
    {
        this.b = 4.0;
    }
}

readonly Klassenfelder werden häufig für Variablen verwendet, die während der Klassenerstellung initialisiert werden und später nie mehr geändert werden.

Kurz gesagt, wenn Sie sicherstellen möchten, dass Ihr Eigenschaftswert niemals von außen geändert wird , Sie ihn jedoch innerhalb Ihres Klassencodes ändern können müssen, verwenden Sie eine "Get-only" -Eigenschaft.

Wenn Sie einen Wert speichern müssen, der sich nach dem Festlegen des Anfangswertes nie mehr ändert, verwenden Sie ein readonlyFeld.

Thibault Falise
quelle
14
+ 1 für Codebeispiel. Es muss jedoch klargestellt werden, dass "Get-Only" -Eigenschaften nur von den Klassenmethoden geändert werden können, wenn sie in Klassenfeldern eingeschlossen sind. Sie können auch von den Klassenmethoden nicht direkt geändert werden, wenn der Setter nicht vorhanden ist. Ein Versuch würde zu einem Compilerfehler führen.
Devraj Gadhavi
13

Ab C # 6 können Sie eine 'schreibgeschützte Auto-Eigenschaft' in einer Zeile deklarieren und initialisieren:

double FuelConsumption { get; } = 2;

Sie können den Wert über den Konstruktor festlegen, jedoch nicht über andere Methoden.

Oberst Panik
quelle
7

Eine Eigenschaft, die nur einen Getter hat, soll schreibgeschützt sein. Es wird kein Setter bereitgestellt, um den Wert der Eigenschaft (von außen) zu ändern.

C # hat ein schreibgeschütztes Schlüsselwort , das für Felder (nicht für Eigenschaften) verwendet werden kann. Ein Feld, das als "schreibgeschützt" markiert ist, kann während der Erstellung eines Objekts (im Konstruktor) nur einmal festgelegt werden.

private string _name = "Foo"; // field for property Name;
private bool _enabled = false; // field for property Enabled;

public string Name{ // This is a readonly property.
  get {
    return _name;  
  }
}

public bool Enabled{ // This is a read- and writeable property.
  get{
    return _enabled;
  }
  set{
    _enabled = value;
  }
} 
Jehof
quelle
2

schreibgeschützte Eigenschaften werden verwendet, um einen ausfallsicheren Code zu erstellen. Ich mag die Encapsulation Posts-Reihe von Mark Seemann über Eigenschaften und Hintergrundfelder sehr:

http://blog.ploeh.dk/2011/05/24/PokayokeDesignFromSmellToFragrance.aspx

entnommen aus Marks Beispiel:

public class Fragrance : IFragrance
{
    private readonly string name;

    public Fragrance(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException("name");
        }

        this.name = name;
    }

    public string Spread()
    {
        return this.name;
    }
}

In diesem Beispiel verwenden Sie das schreibgeschützte Namensfeld, um sicherzustellen, dass die Klasseninvariante immer gültig ist. In diesem Fall wollte der Klassenkomponist sicherstellen, dass das Namensfeld nur einmal gesetzt ist (unveränderlich) und immer vorhanden ist.

danfromisrael
quelle
0

Methoden legen nahe, dass etwas passieren muss, um den Wert zurückzugeben. Eigenschaften legen nahe, dass der Wert bereits vorhanden ist. Dies ist eine Faustregel. Manchmal möchten Sie vielleicht eine Eigenschaft, die ein wenig Arbeit leistet (dh Count), aber im Allgemeinen ist dies eine nützliche Methode, um zu entscheiden.

Neil Barnwell
quelle