Suche…


Bemerkungen

Eigenschaften kombinieren die Klassendatenspeicherung von Feldern mit der Zugänglichkeit von Methoden. Manchmal kann es schwierig sein, zu entscheiden, ob eine Eigenschaft verwendet wird, eine Eigenschaft, die auf ein Feld verweist, oder eine Methode, die auf ein Feld verweist. Als Faustregel gilt:

  • Eigenschaften sollten ohne internes Feld verwendet werden, wenn sie nur Werte erhalten und / oder festlegen. ohne dass eine andere Logik auftritt. In solchen Fällen würde das Hinzufügen eines internen Felds das Hinzufügen von Code ohne Nutzen bedeuten.

  • Eigenschaften sollten mit internen Feldern verwendet werden, wenn Sie die Daten bearbeiten oder validieren müssen. Ein Beispiel ist das Entfernen von führenden und nachgestellten Leerzeichen aus Zeichenfolgen oder das Sicherstellen, dass ein Datum nicht in der Vergangenheit liegt.

Im Hinblick auf die Methoden vs Eigenschaften, wo Sie beide (abrufen get ) und update ( set ) einen Wert, ist eine Eigenschaft , die bessere Wahl. .Net bietet außerdem eine Vielzahl von Funktionen, die die Struktur einer Klasse nutzen. B. ein Raster zu einem Formular hinzufügen, listet .Net standardmäßig alle Eigenschaften der Klasse in diesem Formular auf; Um solche Konventionen bestmöglich zu nutzen, sollten Sie Eigenschaften verwenden, wenn dieses Verhalten normalerweise wünschenswert ist, und Methoden, bei denen Sie bevorzugen, dass die Typen nicht automatisch hinzugefügt werden.

Verschiedene Eigenschaften im Kontext

public class Person 
{
    //Id property can be read by other classes, but only set by the Person class
    public int Id {get; private set;}
    //Name property can be retrieved or assigned 
    public string Name {get; set;}
    
    private DateTime dob;
    //Date of Birth property is stored in a private variable, but retrieved or assigned through the public property.
    public DateTime DOB
    {
        get { return this.dob; }
        set { this.dob = value; }
    }
    //Age property can only be retrieved; it's value is derived from the date of birth 
    public int Age 
    {
        get 
        {
            int offset = HasHadBirthdayThisYear() ? 0 : -1;
            return DateTime.UtcNow.Year - this.dob.Year + offset;
        }
    }

    //this is not a property but a method; though it could be rewritten as a property if desired.
    private bool HasHadBirthdayThisYear() 
    {
        bool hasHadBirthdayThisYear = true;
        DateTime today = DateTime.UtcNow;
        if (today.Month > this.dob.Month)
        {
            hasHadBirthdayThisYear = true;
        }
        else 
        {
            if (today.Month == this.dob.Month)
            {
                hasHadBirthdayThisYear = today.Day > this.dob.Day;
            }
            else
            {
                hasHadBirthdayThisYear = false;
            }
        }
        return hasHadBirthdayThisYear;
    }
}

Öffentlich erhalten

Getter werden verwendet, um Werte aus Klassen anzuzeigen.

string name;
public string Name
{
    get { return this.name; }
}

Öffentliches Set

Setter werden verwendet, um den Eigenschaften Werte zuzuweisen.

string name;
public string Name 
{
    set { this.name = value; }
}

Auf Eigenschaften zugreifen

class Program 
{
    public static void Main(string[] args)
    {
        Person aPerson = new Person("Ann Xena Sample", new DateTime(1984, 10, 22));
        //example of accessing properties (Id, Name & DOB)
        Console.WriteLine("Id is:  \t{0}\nName is:\t'{1}'.\nDOB is: \t{2:yyyy-MM-dd}.\nAge is: \t{3}", aPerson.Id, aPerson.Name, aPerson.DOB, aPerson.GetAgeInYears());
        //example of setting properties

        aPerson.Name = "   Hans Trimmer  ";
        aPerson.DOB = new DateTime(1961, 11, 11);
        //aPerson.Id = 5; //this won't compile as Id's SET method is private; so only accessible within the Person class.
        //aPerson.DOB = DateTime.UtcNow.AddYears(1); //this would throw a runtime error as there's validation to ensure the DOB is in past. 

        //see how our changes above take effect; note that the Name has been trimmed
        Console.WriteLine("Id is:  \t{0}\nName is:\t'{1}'.\nDOB is: \t{2:yyyy-MM-dd}.\nAge is: \t{3}", aPerson.Id, aPerson.Name, aPerson.DOB, aPerson.GetAgeInYears());

        Console.WriteLine("Press any key to continue");
        Console.Read();
    }
}

public class Person
{
    private static int nextId = 0;
    private string name;
    private DateTime dob; //dates are held in UTC; i.e. we disregard timezones
    public Person(string name, DateTime dob)
    {
        this.Id = ++Person.nextId;
        this.Name = name;
        this.DOB = dob;
    }
    public int Id
    {
        get;
        private set;
    }
    public string Name
    {
        get { return this.name; }
        set
        {
            if (string.IsNullOrWhiteSpace(value)) throw new InvalidNameException(value);
            this.name = value.Trim();
        }
    }
    public DateTime DOB
    {
        get { return this.dob; }
        set 
        {
            if (value < DateTime.UtcNow.AddYears(-200) || value > DateTime.UtcNow) throw new InvalidDobException(value);
            this.dob = value; 
        }
    }
    public int GetAgeInYears()
    {
        DateTime today = DateTime.UtcNow;
        int offset = HasHadBirthdayThisYear() ? 0 : -1;
        return today.Year - this.dob.Year + offset;
    }
    private bool HasHadBirthdayThisYear()
    {
        bool hasHadBirthdayThisYear = true;
        DateTime today = DateTime.UtcNow;
        if (today.Month > this.dob.Month)
        {
            hasHadBirthdayThisYear = true;
        }
        else
        {
            if (today.Month == this.dob.Month)
            {
                hasHadBirthdayThisYear = today.Day > this.dob.Day;
            }
            else
            {
                hasHadBirthdayThisYear = false;
            }
        }
        return hasHadBirthdayThisYear;
    }
}

public class InvalidNameException : ApplicationException
{
    const string InvalidNameExceptionMessage = "'{0}' is an invalid name.";
    public InvalidNameException(string value): base(string.Format(InvalidNameExceptionMessage,value)){}
}
public class InvalidDobException : ApplicationException
{ 
    const string InvalidDobExceptionMessage = "'{0:yyyy-MM-dd}' is an invalid DOB.  The date must not be in the future, or over 200 years in the past.";
    public InvalidDobException(DateTime value): base(string.Format(InvalidDobExceptionMessage,value)){}
}

Standardwerte für Eigenschaften

Das Festlegen eines Standardwerts kann mithilfe der Initialisierer (C # 6) erfolgen

public class Name 
{
    public string First { get; set; } = "James";
    public string Last { get; set; } = "Smith";
}

Wenn es nur gelesen wird, können Sie Werte wie folgt zurückgeben:

  public class Name 
  {
      public string First => "James";
      public string Last => "Smith";
  }

Automatisch implementierte Eigenschaften

Automatisch implementierte Eigenschaften wurden in C # 3 eingeführt.
Eine automatisch implementierte Eigenschaft wird mit einem leeren Getter und Setter (Accessor) deklariert:

public bool IsValid { get; set; }

Wenn eine automatisch implementierte Eigenschaft in Ihren Code geschrieben wird, erstellt der Compiler ein anonymes privates Feld, auf das nur über die Zugriffsmethoden der Eigenschaft zugegriffen werden kann.

Die obige automatisch implementierte Eigenschaftsanweisung entspricht dem Schreiben dieses langen Codes:

private bool _isValid;
public bool IsValid
{
    get { return _isValid; }
    set { _isValid = value; }
}

Automatisch implementierte Eigenschaften können keine Logik in ihren Zugriffsmethoden haben, zum Beispiel:

public bool IsValid { get; set { PropertyChanged("IsValid"); } } // Invalid code

Eine automatisch implementierte Eigenschaft kann jedoch unterschiedliche Zugriffsmodifizierer für ihre Zugriffsmethoden haben:

public bool IsValid { get; private set; }    

In C # 6 können automatisch implementierte Eigenschaften keinen Setter enthalten (dies macht sie unveränderlich, da ihr Wert nur innerhalb des Konstruktors festgelegt oder hart codiert werden kann):

public bool IsValid { get; }    
public bool IsValid { get; } = true;

Weitere Informationen zum Initialisieren von automatisch implementierten Eigenschaften finden Sie in der Dokumentation der Auto-Property-Initialisierer .

Schreibgeschützte Eigenschaften

Erklärung

Ein häufiges Missverständnis, insbesondere für Anfänger, ist die schreibgeschützte Eigenschaft, die mit readonly Schlüsselwort readonly gekennzeichnet ist. Das ist nicht korrekt und in der Tat ist ein Fehler bei der Kompilierung :

public readonly string SomeProp { get; set; }

Eine Eigenschaft ist schreibgeschützt, wenn sie nur über einen Getter verfügt.

public string SomeProp { get; }

Verwenden von schreibgeschützten Eigenschaften zum Erstellen unveränderlicher Klassen

public Address
{
    public string ZipCode { get; }
    public string City { get; }
    public string StreetAddress { get; }

    public Address(
        string zipCode,
        string city,
        string streetAddress)
    {
        if (zipCode == null)
            throw new ArgumentNullException(nameof(zipCode));
        if (city == null)
            throw new ArgumentNullException(nameof(city));
        if (streetAddress == null)
            throw new ArgumentNullException(nameof(streetAddress));

        ZipCode = zipCode;
        City = city;
        StreetAddress = streetAddress;
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow