Autor Beitrag
Bennle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: Fr 11.01.08 19:45 
Hallo,
Ich möchte gerne ein "globales" Objekt erstellen welches ich von jeder Form auslesen kann.

Es soll genutzt werden um Konfigurationen zu ändern, lesen und verwenden.

Wie kann ich das realisieren? Ein Beispiel wäre auch nicht schlecht.

Danke.

Gruß
Benny

PS: Hmm ich glaub ich hab mich im Forum vertan! Bitte verschieben!!!


Moderiert von user profile iconChristian S.: Topic aus Allgemeine .NET-Fragen verschoben am Fr 11.01.2008 um 18:47
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 11.01.08 19:51 
Hallo!

Sowas wie eine globale Variable gibt es in .NET nicht mehr. Du kannst aber ein paar andere Dinge tun, sodass Du ähnliches erreichen kannst:

(1) Eine statische Klasse machen mit statischen Eigenschaften.
(2) Ein Singleton-Pattern implementieren

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Bennle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: Fr 11.01.08 20:01 
user profile iconChristian S. hat folgendes geschrieben:
Hallo!

Sowas wie eine globale Variable gibt es in .NET nicht mehr. Du kannst aber ein paar andere Dinge tun, sodass Du ähnliches erreichen kannst:

(1) Eine statische Klasse machen mit statischen Eigenschaften.
(2) Ein Singleton-Pattern implementieren

Grüße
Christian


Danke für die schnelle Antwort!
Ich gehe davon aus, dass der Punkt 1 für mich nicht möglich ist, da die Daten dynamisch sind.

Wird bei Punkt 2 dann immer ein neues Objekt erstellt? Nur nicht angelegt?

Wie baue ich das in meine klasse ein? Habe folgendes: (bitte korrigieren)
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
    sealed class SOFTconfig
    {
        private SOFTconfig() 
        {  /* ...hier optional Initialisierungscode... */ }
        public List<string> testlist = new List<string>();
        public static readonly SOFTconfig Instance = new SOFTconfig() ;

    }


Aufruf in jeder form erfolgt mit:
ausblenden C#-Quelltext
1:
SOFTConfig config = SOFTconfig.Instance ;					


Gruß
Benny


Zuletzt bearbeitet von Bennle am Fr 11.01.08 20:08, insgesamt 3-mal bearbeitet
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 11.01.08 20:02 
Du musst auf das Instance-Feld zugreifen, wie es im Wiki-Artikel steht

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Bennle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: Fr 11.01.08 20:03 
user profile iconChristian S. hat folgendes geschrieben:
Du musst auf das Instance-Feld zugreifen, wie es im Wiki-Artikel steht


Hmm hab ich! Habe versucht es abzuleiten, aber scheinbar stimmt es nicht :(

Ich schau es mir nochmal an!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 11.01.08 20:07 
Versuch am Besten erst einmal, das Prinzip hinter einem Singleton zu verstehen :-)

Das Feld Instance enthält die ganze Zeit über dieselbe (die einzige!) Instanz der Klasse. Diese wird nur einmal bei der Initialisierung der Klasse erstellt. Von außen kann die Klasse nicht erstellt werden, sondern man benutzt immer die Instance-Instanz. Und mit "new" greift man auf kein Feld zu ;-)

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Bennle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: Fr 11.01.08 20:23 
Hey super!
Ich hab's echt zum laufen bekommen!

Nur noch eine kleine Frage.
Bei .Net2 wird eine andere Variante vorgeschlagen. Sollte man sich lieber an die "Generics" gewöhnen? Oder ist das nur für komplexe dinge gedacht. (denn ich brauche bisher ja nur die eine Klasse!)

Gruß
Benny
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 11.01.08 20:25 
Hä? Was haben Generics damit zu tun? Irgendwie hättest Du auch fragen können, ob Du besser ein Taschenmesser als den ICE nimmst :gruebel:

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Bennle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: Fr 11.01.08 20:30 
Ok, sorry! Da ich nicht weiß was es ist und ich nur gelesen habe:
Zitat:

Implementierung eines Generics für Singletons in C# ab .NET 2.0

Habe ich gedacht das es so gang und gebe ist.

Naja macht auch nix.

Danke nochmal.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 11.01.08 21:08 
user profile iconBennle hat folgendes geschrieben:
Ich gehe davon aus, dass der Punkt 1 für mich nicht möglich ist, da die Daten dynamisch sind.
Das hat damit nichts zu tun, das wäre readonly ;) . static bedeutet nur, dass das Feld nicht zu einem Objekt gehört, das erst erstellt werden müsste, sondern zum gesamten Typ. Imho bringen Singletons ggü. statischen Klassen nur in Ausnahmefällen Vorteile, weswegen in allen anderen Fällen eigentlich nichts gegen Letztere spricht.

Zitat:
Sollte man sich lieber an die "Generics" gewöhnen?
Meinst du das speziell oder allgemein? Klar, wenn du nur ein Singleton im gesamten Projekt brauchst, bringt dir die wiki-Basisklasse rein gar nichts, aber allgemein solltest du dich schon mit Generics auseinandersetzen - lieber früher als später.
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Sa 12.01.08 12:20 
Hallo,

user profile iconChristian S. hat folgendes geschrieben:
Hä? Was haben Generics damit zu tun? Irgendwie hättest Du auch fragen können, ob Du besser ein Taschenmesser als den ICE nimmst :gruebel:

Das dachte ich auch, aber unter Generic Singleton ist eine (imo geniale) Lösung vorgestellt:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
public static class Singleton<T> where T : new()
{
    static Mutex mutex = new Mutex();
    static T instance;
    public static T Instance    {
        get        {
            mutex.WaitOne();
            if(instance == null)
                instance = new T();
            mutex.ReleaseMutex();
            return instance;
        }
    }
}

Der große Vorteil ist (Erläuterung im Link) ist: Du bindest Singleton<T> einmal in Dein Projekt ein und kannst sofort jede Klasse als Singleton benutzen, ohne dass Du den Basiscode (der sich ja stets wiederholt) dort implementieren musst.

user profile iconBennle hat folgendes geschrieben:

Habe ich gedacht das es so gang und gebe ist.

Ist es nicht, wie Du an den Reaktionen gemerkt hast.

user profile iconBennle hat folgendes geschrieben:
Sollte man sich lieber an die "Generics" gewöhnen? Oder ist das nur für komplexe dinge gedacht. (denn ich brauche bisher ja nur die eine Klasse!)

Die sind für alle Klassen (und Methoden und Strukturen) geeignet, die gleichartige Verfahren oder Eigenschaften haben. Deshalb sollte man sich grundsätzlich daran gewöhnen. Aber das führt hier zu weit (und ist eigentlich schon OT).

Gruß Jürgen
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Sa 12.01.08 13:03 
@JüTho: Aber dann hat T (von dem ich ja den Singleton haben will) doch einen constructor, der mindestens assembly-Sichtbarkeit besitzt. IMHO ist es bei einem Singleton sauberer, wenn ich die entsprechende Klasse gar nicht instanzieren kann.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Sa 12.01.08 13:23 
user profile iconChristian S. hat folgendes geschrieben:
@JüTho: Aber dann hat T (von dem ich ja den Singleton haben will) doch einen constructor, der mindestens assembly-Sichtbarkeit besitzt. IMHO ist es bei einem Singleton sauberer, wenn ich die entsprechende Klasse gar nicht instanzieren kann.

Das Wörtchen "kann" ist in der Tat von Bedeutung. Dieser Aspekt war mir bewusst (und hat mir bei dieser generellen "genialen" Lösung etwas Bauchschmerzen verursacht), aber ich habe ihn bisher vernachlässigt.

Vielleicht können wir uns auf folgende Zusammenfassung einigen:
  • Wenn der Entwickler sehr diszipliniert arbeitet, kann er auch das "Generic Singleton" verwenden.
  • Sicherer im Sinne der OO ist es auf jeden Fall, dies nicht zu nutzen.

Gruß Jürgen
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Sa 12.01.08 13:25 
user profile iconJüTho hat folgendes geschrieben:
Vielleicht können wir uns auf folgende Zusammenfassung einigen:
  • Wenn der Entwickler sehr diszipliniert arbeitet, kann er auch das "Generic Singleton" verwenden.
  • Sicherer im Sinne der OO ist es auf jeden Fall, dies nicht zu nutzen.
Das fasst es ganz gut zusammen :zustimm:

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Robert_G
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416


Delphi32 (D2005 PE); Chrome/C# (VS2003 E/A, VS2005)
BeitragVerfasst: So 13.01.08 14:46 
user profile iconJüTho hat folgendes geschrieben:
Das dachte ich auch, aber unter Generic Singleton ist eine (imo geniale) Lösung vorgestellt:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
public static class Singleton<T> where T : new()
{
    static Mutex mutex = new Mutex();
    static T instance;
    public static T Instance    {
        get        {
            mutex.WaitOne();
            if(instance == null)
                instance = new T();
            mutex.ReleaseMutex();
            return instance;
        }
    }
}

Der große Vorteil ist (Erläuterung im Link) ist: Du bindest Singleton<T> einmal in Dein Projekt ein und kannst sofort jede Klasse als Singleton benutzen, ohne dass Du den Basiscode (der sich ja stets wiederholt) dort implementieren musst.
Die Lösung iat gar nicht mal so genial.
Denn sie wird stets und ständig Thread-Locks benötigen, wenn du auf die Eigenschaft zugreifst. Das ist sehr langsam & unprofessionell, IMO. (Wobei ich kein Fan von Singletons im Allgemeinen bin ;-) )

Wenn man die Instanz nicht Lazy-Loaded benötigt, dann wäre das hier das wohl effizienteste.
Das Sperren beim Initieren des Typen passiert automatisch, von da an ist der Zugriff auf die Instanz thread-safe:
ausblenden Delphi-Prism-Quelltext
1:
2:
3:
4:
5:
6:
type
  Singleton<T> = public static class
    where T has constructor;
  public
    property Instance : T := new T(); readonly;
  end;

Falls das Instanzieren von T viel Zeit oder T selbst viel Platz benötigt, dann wäre das hier ein effizientes generisches Lazy-Loaded Singleton.
Das Sperren des Threads ist nur solange nötig, bis "GetInstanceCall" umgebogen ist.
Danach wird nur noch direkt die neue Instanz zurück gegeben:
ausblenden volle Höhe Delphi-Prism-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
  LazySingleton<T> = public static class
    where T has constructor;
  public
    property Instance : T read GetInstanceCall();
  private
    GetInstanceCall : GetInstanceHandler;
    
    method InitialGetInstance: T; locked// nur die Methode ist gesperrt
    constructor;
  end;
  
  GetInstanceHandler nested in LazySingleton<T>
    = private delegate : T;
    
implementation

constructor LazySingleton<T>; 
begin
  GetInstanceCall := @InitialGetInstance;
end;

method LazySingleton<T>.InitialGetInstance: T; 
begin
  if not assigned(GetInstanceCall.Target) then // InitialGetInstance ist statisch
  begin
    var newInstance := new T();
    
    GetInstanceCall := method : T;
    begin
      exit newInstance;
    end;
  end;

  exit GetInstanceCall()
end;
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: So 13.01.08 20:31 
Robert, deine Implementierung hat wirklich Stil :shock: . Bin nicht wirklich firm in Sachen Synchronisierung[meta]was vor allem daran liegt, dass Jeffrey Richter zu dem Thema nur auf seine alten Bücher verweist *g*[/meta], aber zwei Fragen dazu:
  • Könnten nicht die gleichen Probleme auftreten wie beim double-checked locking ohne volatile[meta]mit vol. weiß dann erst recht niemand, was passiert...[/meta]? À la "Thread1 hat gerade das Singleton erstellt und Monitor.Exit aufgerufen, Thread2 sieht bei der assigned-Abfrage aber noch den alten Delegaten in seinem Cache und betritt den if-Block"?
  • Um mich mit Richter wieder zu versöhnen: Hieß es dort und auch von Microsoft selbst nicht, dass äußerst dämlicher Architektur wegen nur private Objekte gelockt werden sollten, also genau das, was das Chrome-locked anscheinend nicht tut o.O ?

Am schönsten finde ich allerdings die Methode auf der englischen Wikipedia: Mit der Singleton-Instanz in einer nested class haben wir vollständige lazyness und gleichzeitig von der CLR versprochene Thread-Sicherheit. Lässt sich wiederum nicht so schön in eine generische Klasse packen, aber bei den anderen Implementierungen besteht ja weiterhin das Problem mit dem öffentlichen Konstruktor.
Ich kann den Schluss hier nur unterschreiben - was mich alles aber nicht in der Frage weiterbringt, ob ich je ein Singleton brauchen werde ;) .
Robert_G
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416


Delphi32 (D2005 PE); Chrome/C# (VS2003 E/A, VS2005)
BeitragVerfasst: So 13.01.08 21:05 
user profile iconKhabarakh hat folgendes geschrieben:
Könnten nicht die gleichen Probleme auftreten wie beim double-checked locking ohne volatile[meta]mit vol. weiß dann erst recht niemand, was passiert...[/meta]? À la "Thread1 hat gerade das Singleton erstellt und Monitor.Exit aufgerufen, Thread2 sieht bei der assigned-Abfrage aber noch den alten Delegaten in seinem Cache und betritt den if-Block"

Der Effekt von volatile hier wäre sooooo gering. Ernsthaft, die Checks, die .Net um jedes Stück Code packt, invalidieren die Register so "effizient", dass das caching-Problem zu vernachlässigen ist.

Zitat:
[*]Um mich mit Richter wieder zu versöhnen: Hieß es dort und auch von Microsoft selbst nicht, dass äußerst dämlicher Architektur wegen nur private Objekte gelockt werden sollten, also genau das, was das Chrome-locked anscheinend nicht tut o.O ?
Ich hätte ein lokales "locking" nutzen können, aber im End effekt wird hier nur wieder Monitor benutzt, um die Referenz des lock-Objektes als Mutex zu misbrauchen.
Bei statischen Methoden nutzt Chrome die Referenz auf das type-token[meta]typeOf(...)[/meta], bei Instanzmethoden ist es "self". Das macht es damit alle "locked" member konsistent sperren.
Der Effekt hier ist wieder vernachlässigbar. Der Zeiger auf das type-token ist so konstant wie es in .Net nur geht... ;-)

Zitat:
Am schönsten finde ich allerdings die Methode auf der englischen Wikipedia: Mit der Singleton-Instanz in einer nested class haben wir vollständige lazyness und gleichzeitig von der CLR versprochene Thread-Sicherheit.
Okay, den könnte ich fast noch akzeptieren. Aber was, wenn man ngen nutze?
Ich würde meine erste Version nutzen, die seine 4. wäre.
Zitat:
Lässt sich wiederum nicht so schön in eine generische Klasse packen
Hmpf?
ausblenden Delphi-Prism-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
type
  LazySingleton2<T> = public static class
    where T has constructor;
  public
    property Instance : T read
      LazySingleton2<T>.NestedHelper.Instance;
  end;
  
  NestedHelper nested in LazySingleton2<T>
    = private static class
  private
    class constructorempty;
  public
    Instance : T := new T(); readonly;
  end;

Zitat:
, aber bei den anderen Implementierungen besteht ja weiterhin das Problem mit dem öffentlichen Konstruktor.
Da sehe ich kein Problem.
Mööp<Miep>.Instanz ist immer die gleiche Instanz. Das ist eine mögliche Form eines Singletons.

Zitat:
was mich alles aber nicht in der Frage weiterbringt, ob ich je ein Singleton brauchen werde ;) .
Jupp, IMO zeigen Singletons oft auf die gleichen Probleme im Design wie globale Variablen.
Du willst etwas statisches mit eigenem Status, und dadurch wirfst du Skalierbarkeit weg. (Man hat es halt nur noch einmal)