24 Stimmen

C#: Wie setzt man den Standardwert für eine Eigenschaft in einer partiellen Klasse?

Ich bin sehr neu in C # so bitte mit mir ...

Ich implementiere eine partielle Klasse, und möchte zwei Eigenschaften wie folgt hinzufügen:

public partial class SomeModel
{
    public bool IsSomething { get; set; }
    public List<string> SomeList { get; set; }

    ... Additional methods using the above data members ...
}

Ich möchte beide Datenelemente initialisieren: IsSomething a True y SomeList a new List<string>() . Normalerweise würde ich es in einem Konstruktor tun, aber weil es eine partielle Klasse ist, möchte ich den Konstruktor nicht berühren (sollte ich?).

Wie kann man das am besten erreichen?

Merci

PS Ich bin in ASP.NET MVC arbeiten, Hinzufügen von Funktionalität zu einem bestimmten Modell, daher die partielle Klasse.

42voto

STW Punkte 42452

Aktualisiert für C# 6

C# 6 hat die Möglichkeit hinzugefügt, Auto-Properties einen Standardwert zuzuweisen. Der Wert kann ein beliebiger Ausdruck sein (es muss keine Konstante sein). Hier sind ein paar Beispiele:

// Initialize to a string literal
public string SomeProperty {get;set;} = "This is the default value";

// Initialize with a simple expression
public DateTime ConstructedAt {get;} = DateTime.Now;

// Initialize with a conditional expression
public bool IsFoo { get; } = SomeClass.SomeProperty ? true : false;

Original-Antwort

Automatisch implementierte Eigenschaften können im Klassenkonstruktor initialisiert werden, aber nicht in der Eigenschaft selbst.

public SomeModel
{
    IsSomething = false;
    SomeList = new List<string>();
}

...oder Sie können eine feldunterstützte Eigenschaft verwenden (etwas mehr Arbeit) und das Feld selbst initialisieren...

private bool _IsSomething = false;
public bool IsSomething
{
    get { return _IsSomething; }
    set { _IsSomething = value; }
}

Aktualisierung: Meine obige Antwort klärt nicht die Frage, ob es sich um eine partielle Klasse handelt. Antwort von Mehrdad bietet die Lösung einer partiellen Methode an, die meinem ersten Vorschlag entspricht. Mein zweiter Vorschlag, nicht automatisch implementierte Eigenschaften (manuell implementierte Eigenschaften?) zu verwenden, wird in dieser Situation funktionieren.

9voto

Reed Copsey Punkte 536986

Die erste Eigenschaft (IsSomething) ist ein Boolescher Wert. Sie ist standardmäßig falsch.

Da es sich bei der zweiten Eigenschaft um einen Referenztyp handelt, wird sie standardmäßig auf null gesetzt, ohne dass Sie etwas dafür tun müssen. Sie brauchen den Konstruktor nicht zu berühren, da Referenztypen (Klassen) in .NET automatisch mit null beginnen.

Wenn Sie einen anderen Wert als den Standardwert verwenden möchten, haben Sie zwei Möglichkeiten -

Verwenden Sie zunächst ein Sicherungsspeicherfeld:

private bool isSomething = true;
public bool IsSomething {
    get { return this.isSomething; }
    set { this.isSomething = value; }
}

Zweite Möglichkeit: Fügen Sie es dem Konstruktor hinzu.

Beachten Sie, dass die erste Option keinen zusätzlichen Overhead hat - es ist im Grunde das, was der Compiler tut, wenn Sie eine automatische Eigenschaft verwenden.

7voto

mmx Punkte 400975

Sie können nicht zwei Konstruktoren in zwei Teilen einer partiellen Klasse haben. Sie können jedoch Teilmethoden um etwas Ähnliches zu erreichen:

// file1:
partial void Initialize();
public Constructor() {
    // ... stuff ... initialize part 1
    Initialize();
}

// file2:
void Initalize() {
    // ... further initializations part 2 might want to do
}

Wenn kein Teil einer partiellen Klasse die partielle Methode definiert, werden alle Aufrufe der Methode ausgelassen.

5voto

Simon_Weaver Punkte 129442

WARNUNG für Benutzer von WCF-Teilklassen

Wenn Sie versuchen, eine Eigenschaft zu einer WCF-Proxyklasse hinzuzufügen (die von Add Service Reference generiert wird), werden Sie vielleicht überrascht sein, dass private Felder nicht initialisiert werden, weil offenbar es wird überhaupt kein Konstruktor aufgerufen .

Wenn Sie versuchen, dies zu tun (wie in einigen anderen Antworten vorgeschlagen), wird es nie aufgerufen werden:

    private bool _sendEmail = true;

Dies hat nichts damit zu tun, ob sich das Feld in einer Teilklasse befindet oder nicht.

Sie müssen lediglich ein [OnDeserialized] Attribut, mit dem Sie weitere Initialisierungen für das Objekt vornehmen können. Dies ist Teil von System.Runtime.Serialization und ist daher nur im Kontext der Serialisierung nützlich, wenn man DatenVertragSerialisierer .

public partial class EndOfDayPackageInfo
{
    [OnDeserialized()]
    public void Init(StreamingContext context)
    {
        _sendEmail = true;
    }

    private bool _sendEmail;
    public bool SendEmail
    {
        get
        {
            return _sendEmail;
        }
        set
        {
            _sendEmail = value;
            RaisePropertyChanged("SendEmail");
        }
    }

}

Ein anderer Ansatz ist das "faule Laden" der Eigenschaft - aber dieser Ansatz ist viel weniger elegant.

    private bool _sendEmail;
    private bool _sendEmailInitialized;

    public bool SendEmail
    {
        get
        {
            if (!_sendEmailInitialized)
            {
                _sendEmailInitialized = true;
                _sendEmail = true;  // default value
            }

            return _sendEmail;
        }
        set
        {
            if (!_sendEmailInitialized)
            {
                // prevent unwanted initialization if 'set' is called before 'get'
                _sendEmailInitialized = true;
            }

            _sendEmail = value;
            RaisePropertyChanged("SendEmail");
        }
    }

4voto

Gregoire Punkte 23141

Verwenden Sie dazu nicht die automatische Eigenschaft, sondern den alten Weg

YourType _yourParameter = yourDefaultValue;
public YourType YourParameter
{
   get{return _yourParameter;}
   set{_yourParameter=value;}
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X