Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von sheitman
Thema: Und nochmal eine Feiertagsberechnung
Am im Forum: .NET-Komponenten und C#-Snippets

Hallo,

wollte noch anmerken das die Buß und Bettag Berechnung auch fehlerhaft ist.
Ist mir für 2000, 2006, 2017 und 2023 aufgefallen. Es ist jedes mal der 15. statt der 22.

Laut Buß- und Bettag ist der Feiertag so definiert das es der Mittwoch vor dem 23. November ist. D.h. der Code kann auch sehr stark vereinfacht werden.

Mit folgender Hilfsmethode


public static DateTime GetLastWeekday(this DateTime startDate, DayOfWeek targetDayOfWeek) {
    DayOfWeek startDayOfWeek =  startDate.DayOfWeek;
    if (startDayOfWeek == targetDayOfWeek) {
        return startDate;
    }
    int diff = 0;
    if (startDayOfWeek < targetDayOfWeek) {
        diff = targetDayOfWeek - startDayOfWeek - 7; 
    } else if (startDayOfWeek > targetDayOfWeek) {
        diff = targetDayOfWeek - startDayOfWeek; 
    }
    return startDate.AddDays(diff);
}

Lässt sich der Buß und Bettag dann so berechnen


DateTime GetBussUndBettag(int year) {
    return new DateTime(year, 11, 22).GetLastWeekday(DayOfWeek.Wednesday);
}

@juetho
bei GetOstersonntag, die letzte Zeile, da würde ich anstelle

return Convert.ToDateTime(OsterTag.ToString() + "." + OsterMonat + "." + jahr);
einfach den Konstruktor von DateTime verwenden

return new DateTime(jahr, OsterMonat, OsterTag);

Gruß
Sven

Thema: [Problem]ComboBox slektiert 1. Eintrag automatisch
Am im Forum: GUI: Windows-Forms

hm bin gerade etwas verwirrt... mal geht es mal geht es nicht...
das mit der bindingsource hat funktioniert weil dann garkein event meh hoch geht das sich was geändert hat...

momentan funktioniert das mit suspendlayout aber ich probier mal das mit beginupdate aus

nachtrag: bisher läufts mit beginupdate =)

Thema: [Problem]ComboBox slektiert 1. Eintrag automatisch
Am im Forum: GUI: Windows-Forms

Zitat von JAck30lena
das rein visuelle bekommst du mit suspendlayout beim befüllen und resumelayout nach dem setzten des selectedindex unter kontrolle.
hat bei mir erst dann funktioniert als ich eine bindingsource dazwischen geschaltet habe, aber immerhin gehts nun =)
Zitat von empty.at
Etwas "pfuschiger": Setz das erste Item auf String.Empty :D
gerade das wollt ich ja vermeiden

Thema: [Problem]ComboBox slektiert 1. Eintrag automatisch
Am im Forum: GUI: Windows-Forms

Hallo,

ich habe ein Form was zum Suchen dienen soll. Einige Suchparameter werden als ComboBox dargestellt und sind an eine DataSource gebunden.

Mein Problem dabei ist, dass die ComboBox automatisch das erste Element auswählt.

Mein Wunsch ist aber eher das garnix ausgewählt wird. Foglich setz ich immer den SelectedIndex auf -1, allerdings sieht man zu Laufzeit kurz das 1. Item....

Jemand eine Idee wie man das unter Kontrolle bekommen kann?

Gruß,
Sven

Thema: Verlosung von drei myCSharp.de-T-Shirts
Am im Forum: Ankündigungen

wenn ihr mich fragt sollten alle die oben die falsche antwort auswählen auch was bekommen^^
und wenns nen spötticher titel für nen monat oder so is *G*

Thema: Fünfter Geburtstag von myCSharp.de
Am im Forum: Ankündigungen

Alles Gute dem Forum und der Community.

Vielen dank an das Team und alle Mitglieder im Forum die so oft mit Rat und Tat einem zur Seite standen. Macht weiter so.

P.S. teilweise passen die Hüte richtig gut auf die Avatare drauf (zu Golo schiel)^^

Thema: AppDater (ehemals K_Updater)
Am im Forum: Projekte

also wenn ich das richtig verstanden hab, kannst du im admin programm vom kupdater für ein update einstellen, das er dies unter einen besonderen benutzer machen soll

d.h. der kupdater wird das passwort was ich dort eingebe verschlüsseln und in der config für das update hinterlegen

wenn du nun ein update machst wird er sich das passwort aus der config nehmen und wieder entschlüsseln um dann beim prozess zu verwenden

oder hab ich das verfahren nicht richtig verstanden?

mir gehts im grunde darum das ic hein ähnliches problem habe
ich muß ein programm unter einem anderen context ausführen können, welches ein admin mal angegeben hat

die frage ist nun, wie verwalte bzw. hinterlege ich diese daten richtig?

das primitivste wäre, ich schreib mit benutzernamen und passwort im klartext in eine datei, wo der admin alles eintragen kann und mein programmdas wieder ausliest

da dann jeder 0815 benutzer das auch auslesen könnte wäre das schlecht

also nochmal meine frage:
wie könnte so ein konzept aussehen bzw. wie ist es beim kupdater geregelt?

Thema: AppDater (ehemals K_Updater)
Am im Forum: Projekte

ich hab da mal ne frage zu den inpersofinizieren:

für die ver- und entschlüsselung brauch man ja einen key, und in die anwendung hart codieren is ja sicherlich nicht das gelbe vom ei...

wie genau sähe denn so ein konzept aus?
d.h. wo liegt das verschlüsselte passwort und der dazugehörige key?

Thema: Word mit LateBinding: Interop Assemblies benötigt?
Am im Forum: Office-Technologien

Keiner? Rainbird du auch nicht?

Thema: Word mit LateBinding: Interop Assemblies benötigt?
Am im Forum: Office-Technologien

Hallo,

ich wollte mal einige grundsätzliche Fragen zum Thema Office und LateBinding stellen.
Folgender Ausgangspunkt: Word 2003 ist installiert.

Wenn ich nun über die Interop Assemblies arbeiten möchte müßte ich die ja in mein Projekt einbinden udn dann quasi mit auf den Rechenr ausliefern wo Office läuft damit das funktioniert. Im Falle von Office 2003 kann man die dort ja sogar mit installiren. Soweit so gut.

Nun soll das ganze aber über LateBinding geschehen, d.h. die Referenz wird aus meinem Projekt entfern und alles durch Reflection ersetzt.

Meien Frage nun ist, benötigt der Zielrechner immernoch im Falle von Office 2003 die InteropDateien? Was genau passiert teschnich im Hintergrund beim LateBinding? Wie greift er nun wirklich auf die Objekte zu?

Wenn man nicht ie Interopdateien referenziert sondern den COM-Typen, generiert das studio ja eine Interop Datei. Geschieht das dann hier auch?

Gruß,
Sven

Thema: Designfrage: ArgumentOutOfRangeException oder IndexOutOfRangeException
Am im Forum: Rund um die Programmierung

Zitat von svenson
Tatsächlich wird aber index nach uint gecastet, was der Reflector erkennen kann, aber nicht tut.
Dann schick dem Lutz Roeder mal ne Email^^

Thema: Problem: generische Methode und Typeinschränkung
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

jup, keine angst, das is ja auch net was ich wollte

letzlich war


class A {}
class B {}

class A<T> : A where T : B{}

class B1 : B {}
class B2 : B {}

class A1 : A<B1> {}
class A2 : A<B2> {}

A1 a1 = DoSomething<A1>();
A2 a2 = DoSomething<A2>();
aber das ging so ja nicht :-/

was geht (es compiliert) ist


T DoSomething<T,K>() where T : A<K> where K : B

A1 a1 = DoSomething<A1, B1>();
A2 a2 = DoSomething<A2, B2>();

denk mal damit is das thema auch abgeschlossen =)

Thema: Designfrage: ArgumentOutOfRangeException oder IndexOutOfRangeException
Am im Forum: Rund um die Programmierung

Zum Thema TryXY hab ich noch was nettes gefunden

Zitat
Consider the TryParse pattern for members that may throw exceptions in common scenarios to avoid performance problems related to exceptions.

To implement The TryParse pattern, you provide two different methods for performing an operation that can throw exceptions in common scenarios. The first method, X, does the operation and throws the exception when appropriate. The second method, TryX, does not throw the exception, but instead returns a Boolean value indicating success or failure. Any data returned by a successful call to TryX is returned using an out (ByRef in Visual Basic) parameter. The Parse and TryParse methods are examples of this pattern.
Do provide an exception-throwing member for each member using the TryParse pattern.

It is almost always not correct design to provide only the TryX method because it requires understanding out parameters. Also, the performance impact of exceptions is not an issue for most common scenarios; you should provide methods that are easy to use in most common scenarios.
Exceptions and Performance
Zitat
In deinem Falle ist aber der fehlerhafter Index-Zugriff eine Ausnahme und nicht die Regel. Deswegen die explizite Prüfung in der Regel unnötig. In einem sauberen Programm nie. Also sind Exceptions angezeigt und verbessern die Performance.
Verstehe worauf du hinaus willst.
Zitat
Mit sind Methode, die boolsche Werte statt Exceptions liefern eher suspekt. Hier würde ich die jedenfalls nicht verwenden.
Naja beim Dictionary find ich sie gut, da sie mir letzlich einen Aufruf mehr spart und für den Fall gemacht ist das ich ein Item haben möchte und vorher aber prüfe ob es auch da ist.
Paßt im dem Fall mit dem Index sicher nicht, aber bei Key -> Value Situationen schon wie ich find.

Thema: Designfrage: ArgumentOutOfRangeException oder IndexOutOfRangeException
Am im Forum: Rund um die Programmierung

Zitat von svenson
Ist allerdings richtig, diese Klasse ist auch kein Array. Ich würde allerdings - wenn schon denn schon - auf eine Prüfung verzichten und stattdessen über ein Exception-Handling arbeiten. Spart Performance.
Glaub das Thema wäre einen witeren Thread wert.
Mein Chef mag keine Exceptions so gern, da ja doch rel. teuer und man soll Exception afaik auch nicht als Kontrollstrukturen a la if else benutzen... von daher wäre wohl

bool GetInt(int index, out int i)
für sowas wohl sogar noch eleganter, oder?

Thema: Designfrage: ArgumentOutOfRangeException oder IndexOutOfRangeException
Am im Forum: Rund um die Programmierung

Zitat von svenson
Eine List<T> ist ja auch kein Array.
Zitat
glaube ich nicht
Zitat
* Do not create methods that throw NullReferenceException or IndexOutOfRangeException.

Error Raising and Handling Guidelines
Naja aber es hat intern ein Array, genau wie meine Klasse oben.
Meine Klasse hat auch einen Indexer der aber nichts darüber sagt das ich ein Array intern benutze.

Also wie ich das so sehe hat herbivore (mal wieder ) schon die besten Argumente angeführt:
Zitat
also sauberer wäre schon eine ArgumentOutOfRangeException, damit für den Verwender der Klasse klar ist, dass er "schuld" ist, weil er falsche Argumente übergeben hat. Bei einer IndexOutOfRangeException muss er ja erstmal ermitteln, ob die an seinen falschen Argumenten lag oder an einem Programmierfehler der benutzen Klasse - wobei ich bei einer IndexOutOfRangeException erstmal letztes vermuten würde.

Außerdem ist es für das Verständnis des Codes besser, wenn die Argumente am Anfang geprüft werden und man - quasi durch Code als Dokumentation - gleich sieht, was zulässig ist und was nicht.

Werd mir jetzt mal die Guidelines anschaun^^

Nachtrag:
im Grunde stehts ja auc in de Guidelines bzw interpertiere ich sie so das ich auf den Konsens von herbivore komme:
Zitat
Do not create methods that throw NullReferenceException or IndexOutOfRangeException.
wollte ich ja nie werfen, die Frage war vorher zu prüfen auf das sie nciht auftreten und ne passende Exception werfen oder einfach zulassen, Jacklena's Weg war ja doppelt gemoppelt der eh nicht zur Diskussion stand und auch diesem Guide wiederspricht.

Viel interessanter find ich
Zitat
All code paths that result in an exception should provide a method to check for success without throwing an exception. For example, to avoid a FileNotFoundException you can call File.Exists. This might not always be possible, but the goal is that under normal execution no exceptions should be thrown.
und
Zitat
Throw an ArgumentException or create an exception derived from this class if invalid parameters are passed or detected.
was herbivores Post auch untermauert. ^^

D.h. also ich könnte wenn der Index nicht paßt ne Exception werfen oder aber einen Standardwert zurück geben sodaß keien Exception aufritt, man müßte das halt in der Hilfe vermerken.
Häufig haben solche Methoden ja auch ein boolschen Rückgabewert der angibt ob die Fkt ausgeführt werden konnte. Und für Fälle wo man sowas nicht machen kann gibts ja immernoch die ArgumentExceptions^^

Thema: Designfrage: ArgumentOutOfRangeException oder IndexOutOfRangeException
Am im Forum: Rund um die Programmierung

Guten Morgen.

Gegeben ist folgende Klasse:

class A {
    private int[] iArray;

    public A (int[] iArray) {
        if(iArray == null) {
            throw new ArgumentNullException("iArray");
        }
        this.iArray = iArray;
    }

    public int GetInt_1(int index) {
        if(index < 0 || index ≥ iArray.Length) {
            throw new ArgumentOutOfRangeException("index");
        }
        return iArray[index];
    }

    public int GetInt_2(int index) {
        //wenn index < 0 || index ≥ iArray.Length wird eine
        //IndexOutOfRangeException vom System geworfen
        return iArray[index];
    }
}

Nun stellt sich mir die Frage welches Design (GetInt_1 oder GetInt_2) ist "besser" bzw. wendet ihr an, vielleicht auch warum.
Ich hab bisher immer nach methodik GetInt_1 gearbeitet, da ich Argumente eh meist überprüfe und dann bei nem Indexer das einfach mitmache.
Chef meinet aber im Grunde ist es überflüßige Arbeit das ja das System eh ne Exception schmeißt.

Einzigsten Vorteil den ich gerade sehe ist, das ArgumentOutOfRangeException von ArgumentException erbt, d.h. das Exceptionhandling ist etwas anders da ich auch ArgumentNullExceptions darüber mit fangen kann, während IndexOutOfRangeException ja eine SystemException ist.

Was meint ihr dazu?

Grüße,
Sven

Thema: Problem: generische Methode und Typeinschränkung
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

also die gegeben Klassen waren

public class A {
}

public class B {
}

public class A<T> : A where T : B {
}

und die Methode ist

public static A<T> DoSomething<T> () where T : B

so, nun hab ich folgende Klassen

public class C : B {}
public class D : A<C> {}

diese Klasse möchte ich nun halt benutzen

D d = DoSomething<C>();

und hier tritt logischer Weise der Fehler auf, da quasi


A<C> a = DoSomething<C>();
D d = a;

steht und ich wette auch das ein cast zu ner Exception führt da es ja klar ist das ein A<C> nicht unbedingt ein D ist, Vererbung is ja gerade anders rum...

Was ich erreichen wollte ist aber so wie der Aufruf oben.

nochmal was mein Ziel ist:
Ich hab ne generische Klasse geschrieben von der ich erbe, und ich möcht eine Methode auf alle Erben anwenden können, die aber in einer anderen Klasse liegt.

Aber so einfach scheint das wohl nicht. -.- Die Lösung von weiter oben mit 2 Argumenten entspricht dem auch genau letzlich. Is halt nur rigenwdi blöd das man dem Typargument nicht sagen kann das es ein Typ von der generischen Klasse ist.
A geht deshalb nich weil es sei kann das es demnächst kein A mehr gibt sondern nur noch A<B>.

Momentan seh ich als Lösung nur das ich sowohl A und B als Typparameter mitgebe.

Thema: Problem: generische Methode und Typeinschränkung
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

@herbivore

danke, an sowas hab ich noch garnicht gedacht. =)
klappt auch soweit allerdings hab ich noch das kleinen problem:

Zitat
Cannot implicitly convert type 'A<B>' to 'A'. An explicit conversion exists (are you missing a cast?)

Ne Idee wie ich das ohne Cast wegbekomm, weil der Sinn der generisch machens war eben auch um das casten zu sparen. :-/

Thema: Problem: generische Methode und Typeinschränkung
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

erstmal vielen dank für die hilfe.
hier die ergebnisse: =)

public A<T> DoSomething<A<T>> ()
Type parameter declaration must be an identifier not a type

public T DoSomething<T>() where T : A<T>
The type 'T' cannot be used as type parameter 'T' in the generic type or method 'A<T>'. There is no implicit reference conversion from 'T' to 'A'.

public T DoSomething<T, U>() where T : A<U>
The type 'U' cannot be used as type parameter 'T' in the generic type or method 'A<T>'. There is no boxing conversion or type parameter conversion from 'U' to 'B'.

public T DoSomething<T, U>() where T : A<U> U : B
sagte er mir nen syntaxfehler

public T DoSomething<T, U>() where T : A<U> where U : B
ließ sich erfolgreich compilieren
aber finds igendwie blöd das ich das U da halt noch angeben darf :-/
aber da ich das U eh in der methode brauche muß ich mir das nicht erst über reflection aus dem T rausholen. hat also auch nen vorteil^^

falls aber jemand ne lösung findet wie man den typen auf einen generischen typen eingrenzt, bitte melden =)

Thema: Problem: generische Methode und Typeinschränkung
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hi, hab hie ein kleines Problem mit einer gernerischen Methode.

Also zunächst einmal hab ich folgende Klassen


public class A {
}

public class B {
}

public class A<T> : A where T : B {
}

nun möchte ich eine Methode in einer anderen Klasse definieren die generisch ist, wobei der Typ aber von meiner A<T> Klasse ist... nur wie gibt man sowas an?


public T DoSomething<T>() where T : A<> {
}
geht nicht, aber ich kann ja auch keinen Typen bei A<> angeben. Gibts da irgendwie nen Platzhalter?

Thema: DateTime.Parse mit Zeitzone
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Schau mal ob dir die Klassen TimeZone oder TimeZoneInfo weiterhelfen.

Thema: DateTime.Parse mit Zeitzone
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

benutzt mal ToUniversalTime()

Console.WriteLine(d.ToUniversalTime().ToString("R"));
hats bei mir wieder richtig ausgegeben

hier auch mal nen blogeintrag der sich mit dem thema beschäftigt =)http://blogs.technolog.nl/eprogrammer/archive/2006/05/14/476.aspx

Thema: DateTime.Parse mit Zeitzone
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Zitat
Dort kommt aber als Ergebnis eine Stunde zu viel raus. Also 04.03.08 08:06:00.
und welche zeitzone is das?
ich vermute einfach mal das tostring standardmäßig die lokalen einstellungen benutzt und dir das ding in gmt +1 anzeigt, weshalb du ne stunde zusätzlich bekommst

Thema: Desktophintergrund im Programm
Am im Forum: GUI: Windows-Forms

bekommst du den neine exception in der schule? laute hilfe wirft OpenSubKey eine SecurityException wenn du nicht genug rechte hast.

Thema: Weiterbildung, Aufstiegsmöglichkeiten
Am im Forum: Smalltalk

du könntest zertifizierungen anstreben. bei mircosoft gibts da z.b. einige.

Thema: Wert auf null checken?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

ne das sollte eigentlich funktionieren...

schau doch mal im debugger nach welchen wert ic bei dir hat...

Thema: allgemeine Verständnisfrage zum Buch von Andreas Kühnel
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Zitat
Das leuchtet soweit ein, damit nicht für jedes Objekt unnötig Speicher alloliert wird
das ist aber nicht der grund warum ein klassenattribut benutzt wird...

du benutzt statische sachen wenn du "dinge" brauchst die nicht objektgebunden sind
da du hier zählen möchtest wieviel objekte existieren, geht das nur über ein statisches attribut

Thema: Projektangewandte Fragen!
Am im Forum: GUI: Windows-Forms

unter windows is das \r\n
dafür gibt auch eine konstante, die du quasi plattformunabhängig einsetzen kannst -> Environment.NewLine

oder du formulierst das so um das du WriteLine benutzt...

Thema: Wie String mit " richtig schreiben?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

ich würde dir raten jedes " mit \" zu ersetzen


string s = "10A\"3\" 20 30F\"n\"\"e\"\"\"R\"\" \"s\"\"th\"\"\" 40D\"$\"";

Thema: 2 Listen miteinander vergleichen
Am im Forum: Rund um die Programmierung

wie schauts damit aus?


public class Item {
    public int Id;
    public string Name;
    public int Error;

    public Item() {
        Id = -1;
        Name = String.Empty;
        Error = -1;
    }
}

bool foundId = false; //signalisiert ob ein bItem mit entsprechedner Id gefunden wurde

foreach(Item b in bItems) {
    b.Error = -1;
}

foreach(Item a in aItems) {
    foundId = false;
    foreach(Item b in bItems) {
        if(a.Id == b.Id) {
            foudId = true;
            if(a.Name == b.Name) {
                a.Error = 0;
                b.Error = 0;
            } else {
                a.Error = 1;
                b.Error = 1;
            }
            break;
        }
    }
    if(!foundId) {
        a.Error = 3;
    }
}
foreach(Item b in bItems) {
    if(b.Error == -1) {
        b.Error = 2;
    }
}

kurze erklärung:
also deine klasse item hab ich abgeändert so das error als initialwert -1 is, damit man später sieht ob da schon was geändert wurde

so, also beide leisten werden quasi durchgegangen wobei jedes item aus aItems mit jedem item aus bItems verglichen werden
wenn ein item mit derselben id gefunden wird, wird ein bollsche variable auf true gesetzt
das signalisiert ob es für ein item aus aItems auch ein item aus bItems gab (später wichtig)
vergleich von a und b ist ansonsten gleich wie bei dir geblieben, nur das ich danach die innere schleife abbreche, haben ja unser ergebnis
wenn jedes b aus bItems mit einem a verglichen wurde wird geprüft ob die boolsche variable true oder false is
ist sie false heißt das in bItems haben wir nichts gefunden mit der gleichen id, also setzen wir den errorcode in a auf 3
nachdem jedes item aus aItems abgearbeitet wurde, sollte für jedes item auch ein error code gesetzt sein
in bItems ist für jedes Item ein errorcode gesetzt wo entweder der name gleich war oder unterschiedlich, d.h. alle restlichen haben kein entsprechendes item in aItems
daher die 2. schleife die alle items in bItems durchgeht und prüft ob errorcode -1 is (der initialwert) und dafür dann eine 2 einträgt (a in aItems nicht vorhanden)

nachtrag:
da wir den errorcode von einem Item in bItems als indikator benutzen sollte nwir ihn vor dem ganzen geprüfe auc hwieder zurück setzn auf -1

is halt bissl unschön das wir 2x zusätzlich durch bItems durchlaufen müßen, aber wüßte jetzt auch nicht wie man das eleganter lösen könnten

nachtrag 2:
andere lösung die mir grad einfällt wäre das hier


Dictionary<int, Item> dic = new Dictionary<int, Item>(aItems.Length);
foreach(Item a in aItems) {
    a.Error = 3;
    dic.Add(a.Id,a);
}
foreach(Item b in bItems) {
    Item a = null;
    dic.TryGetValue(b.Id,out a);
    if(a != null) {
        if(a.Name == b.Name) {
            a.Error = 0;
            b.Error = 0;
        } else {
            a.Error = 1;
            b.Error = 1;
        }
    } else {
        b.Error = 2;
    }
}

wäre, schätz ich mal, halt bissl schneller, aber verbrauch bissl mehr speicherplatz
dafür mußt du deine klasse nicht anpassen

nachtrag: von hashtable auf dictionary umgestellt