2009-08-09 16 views
9

Ich benutze C#. Ich habe eine Klasse erstellt, die in jedem C# .net-Projekt (Desktop oder Web) enthalten sein kann, aber ich möchte, dass nur 10 Objekte in dieser Anwendung meiner Klasse erstellt werden. Wenn Objektinstanzen mehr als 10 erstellt haben, sollte es einen Fehler geben oder einfach wird nicht funktionieren.Begrenzen Instanzen erstellen einer Klasse?

Es können zwei Situationen sein,

  1. ich in jedem myclass.cs Datei Projekt eingebunden werden oder
  2. ich meine Klasse in einer DLL bündeln werden und sind dann in jeder Anwendung
  3. wenn mehr als 10 Fälle von meiner Klasse

in beiden Situationen ist es Fehler durch muss in der Anwendung erstellt wird.

Diese Frage wurde von meinem Lehrer gefragt, er sagte mir, nach der Antwort im Internet zu suchen, habe ich versucht, aber nirgendwo eine Lösung für dieses Problem gefunden, habe ich nicht gehört, dass wir Objekte begrenzen können?

Ist es möglich, wenn ja wie?

Dank

+0

Ich denke, Sie haben es richtig gemacht, ausreichend privilegierter Code wird immer in der Lage sein, jede auferlegte Grenze zu umgehen. – CurtainDog

Antwort

17

Halten Sie eine statische Variable mit der Anzahl der Instanzen erstellt. Erhöhen Sie diese Zahl bei jeder Konstruktion des Objekts. Machen Sie das Objekt IDisposable und dekrementieren Sie diese Nummer bei jedem Aufruf von Dispose(). Wenn Sie möchten, dass es threadsicher ist, verwenden Sie Interlocked.Increment() und Interlocked.Decrement(), um den Wert dieser Variablen anstelle von ++ und - zu ändern.

+0

Verwenden von Destruktoren ist mehr fehlersicher. – Dykam

+0

Dies ist fast das Gleiche wie eine Variation des Singleton-Musters, mit dem eine bestimmte Anzahl von Instanzen erstellt werden kann. –

+7

Dykam: Das ist C#. C# hat keine Destruktoren, es hat nichtdeterministische Finalizer. Wenn Sie die Anzahl im Finalizer dekrementieren, können Sie sich für Fälle einrichten, in denen Ihre Klassen alle außerhalb des Gültigkeitsbereichs liegen, aber noch nicht von der Garbage-Collection erfasst wurden und Sie keine weiteren Objekte erstellen können. –

8

Ich glaube, dass Sie irgendeine Form der multiton pattern wollen.

Die MULTITON ist eine Variation der Singletonmuster, aber das ermöglicht n Instanzen eines Objekts. Ähnlich wie die Singleton-Klasse eine statische Variable für die einzelne Instanz hat, wird die Multiton oft mit einem statischen Array oder einer Instanz-Map implementiert, abhängig davon, wie Sie auf die Instanzen zugreifen möchten - Arrays erlauben nur numerischen Zugriff, aber durch Verwendung In einer Map können Sie String-Schlüsseln für Ihre Instanzen angeben und sie so benennen.

+0

Ja, Sie können das sagen, aber ich möchte es bis 10 Instanzen begrenzen, die bis 15 oder 20 usw. variieren können. – Prashant

+0

Es ist immer noch möglich mit dem Multiton. Verwenden Sie statt eines Arrays einen in der Größe veränderbaren Container. –

+0

Also eine statische Variable in einer Klasse zu halten ist ein "Muster" in diesen Tagen eh? –

7

Sie müssen einfach die factory pattern mit einem Zähler der Anzahl der erstellten Instanzen verwenden, nach denen die Factory-Methode eine Ausnahme/Null zurückgeben wird.

Beispiel:

public class Foobar 
{ 
    private static int numInstances = 0; 

    public static Foobar CreateFoobar() 
    { 
     if (numInstances++ < 10) 
     { 
      return new Foobar(); 
     } 

     return null; 
    } 

    protected Foobar() 
    { 
     ... 
    } 
} 

Das obige Verfahren wird für eine einzelne Instanz Anwendung sehr gut funktionieren, aber für eine Multi-Instanz-Anwendung, werden Sie wahrscheinlich wollen eine semaphore (eine Implementierung in System.Threading besteht verwenden), die für genau diese Situation gedacht ist (Beschränkung des Zugriffs auf Ressourcen/Objekte). Es löst das Problem, dass mehrere Instanzen der Klasse fast gleichzeitig angefordert werden, und die Zählung schlägt fehl.

+0

Das einzige Problem bei der Verwendung dieser Funktion in der Factory ist, dass die Factory weniger wiederverwendbar ist, da sie an eine bestimmte Implementierung einer Anwendung gebunden ist, da sie weiß, wie viele Instanzen diese Anwendung benötigt. –

+0

@Thomas Owens: Wenn das ein Problem für das OP ist, kann er immer das abstrakte Fabrikmuster verwenden. :) – Noldorin

+1

Wann und wie wird "numInstances" verringert? –

0

Ich würde eine statische Ganzzahl erstellen und aktualisieren, wenn Sie ein neues Objekt instanziieren.

class YourClass 
{ 
    static int Count = 0; 

    public YourClass() 
    { 
     Count++; 
     if(Count > 10) 
     { 
      //throw exception 
     } 
    } 
} 
+1

Es ist nicht Thread-sicher, und Sie erhöhen Count zweimal bei jeder Initialisierung. –

+0

Ja, es ist nicht Thread-sicher, aber es ist ein einfaches Beispiel, das den Punkt herüberbringt. Und ich reparierte die doppelten Inkremente, danke: D – bufferz

+2

Auch du verringerst nie Count –

0

einen statischen Zähler in der Klasse nehmen, und eine Ausnahme in der Klasse Konstruktor werfen, wenn count> 10

0

Zum Beispiel der Entsorgung auch ein statisches Entlade-Verfahren (ähnlich AppDomain) erstellen. Rufen Sie die Unload-Methode auf, rufen Sie die Implementierung von IDisposable auf, die den Zähler mithilfe von Interlocked.Decrement dekrementiert und außerdem die Instanz entsorgt.

(Ich gehe davon aus, wenn Ihr die Anzahl der Instanzen zu begrenzen Sie Ressourcen in der Instanz zu verwalten.)

Sie auch Generika können die Factory-Klasse zu ermöglichen, zur Begrenzung Instanzen verschiedener werden wiederverwendet Klassen. Verwenden Sie Integritätsbedingungen, um eine Instanz zum Implementieren von IDisposible zu benötigen, und verfügen Sie über einen Standardkonstruktor. Stellen Sie außerdem eine nicht statische Eigenschaft bereit, um die tatsächliche Instanz zurückzugeben.


public class foo : IDisposable 
    { 
    public foo() { ; } 
    public string Name; 

    public void Dispose() { ; } 
    // Real class would free up instance resources 
    } 

    LimitedInstance<foo> li = LimitedInstance<foo>.CreateInstance(); 

    li.Instance.Name = "Friendly Name for instance"; 
    // do stuff with li 

    LimitedInstance<foo>.UnloadInstance(ref li); 

Das einzige Problem ist, dass Sie nicht den Zuweisungsoperator in C# überlasten kann. Also, wenn Sie wie folgt vorgehen:


    li = null; 

Anstatt das Entlastungsverfahren Aufruf dann die Instanz auf dem Heap bleiben und Ihre Zähler Anzahl der Instanzen wird nicht verringert werden, bis GC auftritt.

Verwandte Themen