2010-05-02 5 views
8

Ich mag so etwas wie dies tun:Ist es eine schlechte Übung, den Status in einer statischen Klasse zu haben?

public class Foo { 
    // Probably really a Guid, but I'm using a string here for simplicity's sake. 
    string Id { get; set; } 

    int Data { get; set; } 

    public Foo (int data) { 
     ... 
    } 

    ... 
} 

public static class FooManager { 
    Dictionary<string, Foo> foos = new Dictionary<string, Foo>(); 

    public static Foo Get (string id) { 
     return foos [id]; 
    } 

    public static Foo Add (int data) { 
     Foo foo = new Foo (data); 
     foos.Add (foo.Id, foo); 

     return foo; 
    } 

    public static bool Remove (string id) { 
     return foos.Remove (id); 
    } 

    ... 

    // Other members, perhaps events for when Foos are added or removed, etc. 
} 

Dies würde mir erlauben, die globale Sammlung von Foo s von überall zu verwalten. Allerdings wurde mir gesagt, dass statische Klassen immer zustandslos sein sollten - Sie sollten sie nicht zum Speichern globaler Daten verwenden. Globale Daten scheinen im Allgemeinen verpönt zu sein. Wenn ich eine statische Klasse nicht verwenden sollte, was ist der richtige Weg, dieses Problem anzugehen?

Hinweis: Ich habe eine similar question finden, aber die Antwort gibt es nicht wirklich in meinem Fall.

Antwort

9

Wer bleibt, dass statische Klassen zustandslos sein sollten? Statisch bedeutet angegeben.

nur wissen, wie statische Klassen in der CLR arbeiten:

  • Sie nicht die Zeit steuern kann, wenn statischen Konstruktoren aufgerufen werden.
  • Statische Klassen haben für jedes aufrufende Programm einen separaten Status.

Auch Concurrency-Probleme beachten.

Als eine Randnotiz, es erstaunt mich, wie oft Leute sagen "Verwenden Sie nicht X." Es wäre, als würde jemand in deinen Werkzeughäuschen gehen und auf ein halbes Dutzend Werkzeuge zeigen und sagen: "Diese Werkzeuge sind eine schlechte Übung." Es macht keinen Sinn.

+1

Ja, wir sollten alle mehr globale Variablen und gotos verwenden ... – Lucas

+1

Verwenden Sie es, wenn Sie müssen, aber klug sein, Probleme zu vermeiden. Später sollte man agil sein, um etwas Besseres zu erreichen. –

3

Was Sie hier suchen, ist eine Singleton-Klasse, keine statische Klasse. Statische Klassen und Methoden sollten für statusfreie Routinen angegeben werden. Eine Singleton-Klasse wird nur einmal pro Anwendungslauf instanziiert und hat die volle Funktionalität einer Klasse als solche. Jedes Mal, wenn Sie es in der Zukunft referenzieren, erhalten Sie die exakt gleiche Instanz mit genau denselben Elementeigenschaften zurück.

Das erste Google-Ergebnis für "C# Singleton" scheint eine ziemlich anständige Erklärung für die Implementierung zu haben. http://www.yoda.arachsys.com/csharp/singleton.html

+1

Beachten Sie jedoch, dass Singletons auch keine gute Methode sind, weil sie Abhängigkeiten usw. erzeugen. Am Ende wären IoC (Inversion of Control) und Dependency Injection eine bessere Lösung. – Femaref

4

Globale Daten sind sowohl leistungsfähig als auch eine häufige Quelle von Problemen, weshalb Techniken wie Dependency Injection verwendet werden. Sie können sich das als normales Entkopplungsproblem vorstellen. Globale Daten, die direkt an vielen Stellen in Ihrem Programm referenziert werden, bilden eine starke Kopplung zwischen diesen globalen Daten und all diesen Orten.

In Ihrem Beispiel haben Sie jedoch den Zugriff auf die Daten in eine Klasse isoliert, die die genauen Details des Zugriffs auf die globalen Daten steuert. Da einige globale Daten oft unvermeidlich sind, halte ich das für einen guten Ansatz.

Sie können zum Beispiel vergleichen, wie app.config und web.config über das .NET-Framework verwendet werden. Sie werden über eine statische Klasse System.Configuration.ConfigurationManager mit einer statischen Eigenschaft AppSettings aufgerufen, die die Details zum Erreichen der globalen Daten verbirgt.

2

Es ist nicht generell schlecht. In einigen seltenen Fällen ist es notwendig, dies zu tun, als etwas anderes mit großem Aufwand zu implementieren.

Es wird jedoch empfohlen, auf Thread-Sicherheit zu achten.

Sie sollten jeden Anruf in Ihrem Wörterbuch sperren, damit nur ein Thread gleichzeitig darauf zugreifen kann.

+0

Ich würde hinzufügen: "Sie sollten jeden Aufruf Ihres Wörterbuchs sperren", wenn Sie in Multithreading-Umgebung arbeiten. Sonst wird es nutzlos sein Overhead – Budda

+0

Hmm, vielleicht hast du recht. Aber meine Erfahrung sagt mir, dass es besser ist, immer so zu machen. Ich arbeite in einer Firma, die jetzt fast alles umgestalten muss, weil sie ursprünglich nicht für Multithreading-Umgebungen implementiert wurde. Ich denke, das kostet viel mehr, als es das erste Mal threadsafe zu implementieren, obwohl Sie diese Sicherheit vielleicht nicht brauchen. – DHN

0

Verwenden Sie eine schreibgeschützte statische Eigenschaft in Ihrer Klasse, diese Eigenschaft wird für alle Instanzen der Klasse gleich sein. Inkrementieren und dekrementieren wie benötigt vom Konstruktor usw.

0

Ich benutze Listen in statischen Klassen die ganze Zeit für Dinge, die nie (oder extrem selten) ändern - praktisch für das Laden von Pick-Listen und solche, ohne jedes Mal die db zu treffen. Da ich keine Änderungen zulasse, muss ich mich nicht um Sperren/Zugriffskontrolle kümmern.

0

Eine andere Sache zu berücksichtigen ist die Anwendung selbst und das Budget dafür. Ist wirklich etwas komplexer als eine statische Klasse?