Frage

Wenn einige Referenztypeigenschaften für ein Projekt der Einrichtung arbeite ich an, ich kam accross ein paar Eigenschaften, die sie ordnungsgemäß verwendet werden initialisiert benötigt werden, um und sollte niemals null sein. Ich habe ein paar Möglichkeiten gesehen, dies zu umgehen und nicht wirklich feststellen kann, ob es irgendwelche wesentliche Nachteile zu einem der wichtigsten Methoden sind habe ich gesehen zu behandeln. Ich möchte die Meinung der Gemeinschaft über den besten Weg, um dies zu handhaben und was die möglichen Nachteile jeder Methode sein könnte.

eine einfache Klasse gegeben, ich habe mehr Möglichkeiten gesehen zu handhaben, dass eine Eigenschaft, nie eine Null-Version dieser Klasse in einer Eigenschaft hat

public class MyClass
{
  //Some collection of code
}

Option 1 - Initialisieren Sie den Sicherungsspeicher

public class OtherClass1
    {
        private MyClass _mC = new MyClass();
        public MyClass MC
        {
            get { return _mC; }
            set { _mC = value; }
        }
    }

Option 2 - Initialisieren Sie die Eigenschaft im Konstruktor

public class OtherClass2
    {
        public MyClass MC { get; set; }     

        public OtherClass2()
        {
            MC = new MyClass(); 
        }
    }

Option 3 - Griff Initialisierung wie im Getter erforderlich

public class OtherClass3
    {
        private MyClass _mC;
        public MyClass MC
        {
            get
            {
                if (_mC == null)
                    _mC = new MyClass();
                return _mC; 
            }
            set { _mC = value; }
        }
    }

Ich bin sicher, es gibt andere Möglichkeiten, aber diese sind diejenigen, die in den Sinn kommen, und ich habe gesehen. Ich versuche meistens, um zu bestimmen, ob es ein gut etabliert Best Practice ist auf diesem oder wenn es ein besonderes Anliegen mit einem der oben genannten.

Cheers,

Steve

War es hilfreich?

Lösung

Die beste Option, wenn Sie wirklich können weg mit nur eine neue Instanz selbst zu schaffen. Nur Konstrukteure schaffen, die alle erforderlichen Werte annehmen, und bestätigen Sie sie an diesem Punkt

Andere Tipps

Soweit ich weiß, gibt es nicht eine etablierte Best-Practice hier aus einem einfachen Grund: Jede der Optionen hat eine andere Leistung / Speicherbedarf Profil. Die erste Option ist geeignet für einen Verweis auf ein Objekt, das Sie wissen müssen, in einer Klasse instanziiert werden, die Sie sicher sind, verwendet werden. Ehrlich gesagt, obwohl ich nie diesen Ansatz, weil ich denke, dass # 2 ist nur besser geeignet; nur ein Gefühl, dass das ist, was ein Konstruktor ist für .

Die letzte Option ist angezeigt, wenn Sie nicht sicher, ob eine Option verwendet wird. Es ermöglicht Ihnen, die Ressource nehmen nur nach Bedarf.

BTW, ist diese Frage richtig „nebenan“ zu einer Reihe von anderen Themen wie die richtige Verwendung des Musters Singleton, die Verwendung von abstrakten Klassen oder Schnittstellen für aufgeschobenes Objekt usw., die für Sie nützlich sein könnten, um erforschen, um einen besseren Einblick zu gewinnen.

Update: Es scheint mir, dass es zumindest in einem Fall ist, wo eine Instanz in der Klassendefinition der Initialisierung ist angemessen (Ihre Option # 1). Wenn die Instanz statisch sein wird, dann ist dies der einzige geeignete Ort initialisieren:

private static readonly DateTime firstClassDate = DateTime.Parse("1/1/2009 09:00:00 AM");

ich daran gedacht, wenn die obige Codezeile in einigen Unit-Tests Erstellen ich heute schreibe (die Nur-Lese ist optional WRT meinen Punkt aber angemessen in meinem Fall).

In Anlehnung an eine Frage, die ich vor ein paar Tagen geschrieben, aber ich denke, dass es hilfreich sein kann, Code Regeln durchzusetzen und sicherzustellen, dass Nulls ein Re nicht verwendet, wo man sie nicht will:

Microsoft gerade veröffentlicht -Code Contracts , ein Werkzeug, das integriert mit Visual Studio und ermöglicht es Ihnen, Verträge für Ihren .NET-Code zu definieren und bekommen Laufzeit und kompilieren Zeit zu überprüfen.

Sehen Sie den Video-on-Channel 9 , das zeigt, wie es verwendet wird.

Für jetzt ist es ein Add-on, aber es wird ein Teil der Basisklassenbibliothek in .NET 4.0

sein

Unter der Annahme, es gibt keine Nebenwirkungen in Bezug auf, wenn _mc instanziert wird, (dh alle anderen Faktoren gleich sind), ziehe ich die Option 3 als dass der Aufwand für eine zusätzliche Instanz von MyClass auf dem Heap in dem Fall speichert, wo die Getter MC nie aufgerufen wird.

Option (3) hat den Vorteil, nicht das Objekts Zuweisung, bis es gebraucht wird, kann es leicht zu einer Verzögerung zu ladende Objekt (so angepasst werden, wenn ein Objekt aus einer Datenbank geladen - hält einen Einfluß von Fremdschlüssel der laden Voll Kind-Objekt, wenn erforderlich)

Optionen 1 & 2 sind syntaktisch anders, aber im Wesentlichen gleichwertig. Option 3 ist ein fauler init Ansatz, den ich sehr konsequent nutzen.
Ich denke, sie alle haben ihren Nutzen, und es hängt davon ab, was Sie brauchen.

Als erstes sollte die Eigenschaft nie null sein oder nie null bei der Initialisierung? Ich vermute, dass Sie die ehemalige bedeutete in diesem Fall Ihre Setter Code nulls gesetzt zu verhindern, muss zu werden.

Das Grundmuster ist hier, dass die äußeree Klasse Zustand, wenn das innere Klassenfeld nicht ungültig ist eine gültige Zuweisung erhalten hat. In diesem Fall sollten nicht nur die Setter verteidigen das Feld von null, aber der Konstruktor sollte seine auf den korrekten Wert initialisiert gewährleisten.

Der Code setzt voraus, dass die äußere Klasse kann beispielsweise die innere Klasse ohne weitere Eingabe von dem Verbraucher-Code. In der realen Welt braucht die äußere Klasse weitere Informationen von außen, um entweder eine bestehende Instanz der inneren Klasse oder genügend Informationen erhalten dafür ein abgerufen werden.

Option 1 ist die Vanille Art und Weise. Da zurück in den alten Tagen haben wir nicht automatisch implementierte Eigenschaften hatte (mit der {get; set;} sintax). So war sie, wie das Standardverhalten angeben

Wenn die Auto-Umgesetzt wird eingeführt, da man nicht direkt das Feld verwenden, um den Standardwert (_mc) speichert, eine ziemlich gute Frage erhebt sich: „Wo finde ich es initialisieren?“

  • Option 2 wird aufgerufen eager loading :., Sobald die Klasse erstellt wird
  • Option 3 genannt verzögertes Laden :. Nur so schnell wie es braucht

Ich habe gesehen, dass die allgemein akzeptierte Art und Weise ist die Option 2: eager loading, , aber ich glaube, dass dies nur Code zu minimieren ist, die vollständig akzeptabel ist. Problem kommt, wenn Sie mehrere Konstruktoren mit mehreren Signaturen beginnen mit und Sie am Ende alle von ihnen zeigt auf eine void Initialize () Methode von einer Art.

Ich ziehe es vor allem Option 3 , da es pro Feld / Eigenschaft sowohl mehr deklarative ist, und es wird Speicher optimiert.

Werfen Sie einen Blick auf EntityFramework mit den verschiedenen Geschmacksrichtungen: Code-First oder Datenbank-erste und Sie werden feststellen, wie für integrierte Eigenschaften es eifrig Lader verwendet, während für Navigationseigenschaften begünstigt (standardmäßig kann angepasst werden) faul Lader .

Auch nehmen in Rechnung, was in diesem Lader vor sich geht. In Entity Framework bedeutet dies, dass jedes Mal, wenn Sie es initialisieren eine Reise in die Datenbank macht und fragt einen Teil davon. Sie bekommen könnten reall schnell von Ihrem DBA mit mehreren Sitzungen gleichzeitig nagen und möglicherweise einige Transaktionen in einzelnen Nutzlasten zentralisieren wollen, daher einige Neuverkabelung eifrig Lader tun könnten ins Spiel kommen ... obwohl Sie große Mengen an Abfragen werden am Ende Daten und verlangsamen Ihre UX.

Code-First können Sie das folgende Beispiel:

public class Blog
{ 
    public int BlogId { get; set; } 
    public string Name { get; set; } 
    public string Url { get; set; } 
    public string Tags { get; set; } 

    public virtual ICollection<Post> Posts { get; set; } 
}

In der obigen Beiträge Sammlung als virtuelle erklärt, wie es zur Laufzeit geändert werden, je nach Einstellung. Wenn Sie es bis zum eifrigen Laden gesetzt ist, wird es tun es als Option 2 , während, wenn Sie es zu faul gesetzt ist, wird es auf ähnlich geändert werden Option 3

Ich hoffe, das war hilfreich

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top