Visual Studio 2010 hängt bei Tests

Vor kurzem hat ich ein ärgerliches Problem mit dem Visual Studio. Sobald irgendwelche Aktionen im Visual Studio 2010 im Zusammenhang mit Tests ausgeführt wurden (sei es Test run/debug, TestListView oder die Standard Test Übersicht) blieb der Visual Studio Prozess devenv.exe mit 100% Prozessorlast hängen. Auch nach einigen Stunden hat sich das Problem nicht gelöst und es war nur noch ein “abschießen” des Prozesses möglich. Dies machte die Verwendung von Tests nicht mehr möglich. Nach langem Probieren und Suchen habe ich den Grund dafür gefunden:

Dafür verantwortlich ist die Datei testimpactdata.sdf welche eine Größe von sage und schreibe 356MB hatte. Nach dem Löschen dieser Datei lief wieder alles wie gewohnt.

Singleton Pattern in C#

Auf Singeltons an sich möchte ich nicht näher eingehen. Wer mehr darüber wissen will, sollte sich die Webseite Implementing the Singleton Pattern in C# einmal anschauen. Dort wird das Was, Wie, Warum sehr gut erklärt. Um nun selber schnell und einfach ein Singleton Pattern auf eine Klasse anzuwenden benötigt es einige Zeilen Code. Dies lässt sich mit einer Generischen Klasse, von der man die jeweilige Klasse ableiten lässt, erheblich einfacher lösen. Der folgende Codeschnipsel ist alles was man dafür benötigt. Nun kann man alle Methoden über das Instance Feld aufrufen.

   1: public class Singleton<T> where T : new()

   2: {

   3:     public static readonly T Instance = new T();

   4: }

Die Singleton Pattern Klasse.

   1: public class NewSingletonClass : Singleton<NewSingletonClass>

   2: {

   3:     public NewSingletonClass()

   4:     {

   5:         // Some code which should be executed only once in the lifetime of the process

   6:     }

   7:

   8:     public Boolean SomeMethod()

   9:     {

  10:     }

  11: }

Die Klasse, welche als Singleton fungieren soll.

   1: NewSingletonClass.Instance.SomeMethod();

So werden die Methoden am Ende aufgerufen. Der Konstruktor der NewSingletonClass wird dabei nur ein mal aufgerufen. Bei Multiprozessor Systemen sollte dies natürlich mit bedacht eingesetzt werden. Aber vor allem im Web-Bereich hat man schon enorme Vorteile wenn sehr teure Operationen im Konstruktor nur ein mal ausgeführt werden.

C# Collections im Vergleich II – Speicherverbrauch

Im letzten Artikel bin ich auf die Unterschiede der einzelnen Collections in Bezug auf Ihre Performance beim Einfügen und Prüfen auf Vorhandensein eingegangen. Nun soll einmal der Speicherbedarf der verschiedenen Datenstrukturen verglichen werden. Dabei wurde direkt vor dem Füllen der Datenstruktur der Speicher des .Net Garbage Collectors gemessen und direkt danach. Die Differenz von beiden Werten ist der gesamte Speicherbedarf der Collection.

Single-Value-Collections

Bei den Single-Value-Collections wurde als Wert ein String der Länge 36 verwendet welcher mit Hilfe der Guid.NewGuid().ToString() jedes mal neu erzeugt wird.

Single-Value Collections 100.000 1.000.000 10.000.000
ArrayList 11.396.592 111.629.736 1.173.602.696
ArrayList(NumOfItems) 11.706.728 111.018.488  
ArrayList.Sort 11.703.859 111.466.131  
HashSet<String> 11.709.379 131.885.997 1.399.452.312
LinkedList<String> 14.587.467 152.557.384 1.519.969.672
List<String> 11.395.749 111.473.453 1.173.606.920
Queue 31.153.069 111.467.472  
Queue(NumOfItems) 25.287.384 111.019.853  
Queue<String> 24.586.963 111.470.693 1.173.606.608
Stack 22.280.301 118.838.109  
Stack<String> 21.580.816 111.472.136 1.173.606.592

Key-Value-Collection

Bei den Key-Value-Collections waren sowohl Key als auch Value je ein unterschiedlicher 36 Char langer String.

Key-Value Collections 100.000 1.000.000 10.000.000
SortedDictionary<String, String> 11.709.317 264.851.285 2.641.653.440
Dictionary<String, String> 11.709.333 248.879.936 2.417.537.728
SortedList<String, String> 22.293.435 224.418.968  
Hashtable 11.985.773 248.635.355 2.425.247.584

 

Den Quellcode des Programmes zum Messen der Collections kann man hier downloaden.

C# Collections im Vergleich

Das C# .Net Framework 3.5 bietet eine Vielzahl an verschiedenen Datenstrukturen um Werte zu speichern – sogenannte Collections. Welche nun die Richtige ist richtet sich vor allem nach der jeweiligen Verwendung und demnach auch nach der Performance der Collection. Ein kleiner Vergleich soll bei der Wahl der richtigen Struktur helfen. Dafür wird jeder Collection dieselbe Anzahl an Objekten hinzugefügt und die Zeit die dafür benötigt wird gemessen. Danach wird in einer Schleife mehrfach ein nicht vorhandenes Objekt gesucht und ebenfalls wieder gemessen. In diesem Artikel soll die Größenbeschränkung auf Grund eines 32bit Systems und der maximalen Größe in Bytes einer Collection keine Rolle spielen.

 

System.Collections

Der Namespace System.Collections (in der mscorlib) beinhaltet alle nicht generischen Collections.

ArrayList

Die ArrayList ist im Prinzip nichts anderes als ein normales Array welches beliebig wachsen kann. Die Startgröße des Arrays ist 4. Sollte bei einem Einfügen die Größe nicht mehr ausreichen, so verdoppelt sich die mögliche Anzahl an Elementen – sollte dies durch ein AddRange nicht ausreichen so wächst es um die Anzahl der neuen Elemente. Das Verdoppeln (und Einfügen mit AddRange) erfolgt durch ein einfaches Array.Copy.

Ein Lookup mit Contains geht jedes Element durch und prüft mit Hilfe von Equals ob die Bedingung erfüllt ist. Deshalb sollte man tunlichst diese Methode NICHT verwenden. Die ArrayList bietet eine erheblich performantere Variante an: die BinarySearch. Diese beginnt mit einem Mittelwert einer Ober- und Unter-Grenze und vergleicht den gefunden Wert. Je nach dem ob er größer oder kleiner ist wird der Mittelwert dementsprechend angepasst.

Durch das Bereitstellen eines genügend großen Arrays und auf Grund des performanten Array.Copy bietet sich diese Struktur für ein schnelles Einfügen an. Müssen einzelne Werte auf Vorhandensein geprüft oder abgerufen werden so sollte die schnelle BinarySearch verwendet werden. Dies kommt zwar noch lange nicht an einen Hash heran aber ist schon nicht so schlecht.

Hashtable

Die Hashtable speichert beliebige Key-Value Paare ab. Dabei wird ein Hashwert basierend auf dem Key (und der Anzahl an bereits eingefügten Werten) berechnet und einem Array hinzugefügt. Im Grunde unterscheidet sich die Hashtable nicht groß vom Dictionary (mal abgesehen davon, dass sie nicht generisch ist).

Queue

Die Queue ist eine Implementierung einer FIFO Struktur. Das Element welches zuerst hineingepackt wird, kommt auch als erstes wieder heraus. Auch hier wird intern ein Array von Objekten verwendet sowie jeweils einen Zeiger auf das erste und letzte Element. Somit ist das Einfügen ähnlich schnell wie auch bei der ArrayList, jedoch gibt es keine Performante Möglichkeit auf das Vorhandensein eines Objektes zu prüfen. Durch einen geeigneten growFactor Wert (zwischen 1.0 und 10.0 – gibt den Prozentsatz an, um den das Array, basierende auf der derzeitigen Größe, wächst) kann beim Anlegen der Queue die Performance nochmals gesteigert werden.

SortedList

Die SortedList speichert Key-Value Werte in zwei Arrays ab. Dabei wird vor dem Einfügen mit Hilfe der BinarySearch die letzte untere Grenze ermittelt (BinarySearch gibt immer die letzte untere Grenze als negativen Wert zurück). Der LookUp auf einen Key erfolgt wiederum mit einer BinarySearch.

Stack

Der Stack stellt eine typische LIFO Datenstruktur dar. Wie auch die anderen einfachen Listen basiert er auf einem Array von Objekten welches automatisch um das Doppelte anwächst, sollte der Platz nicht mehr ausreichen. Wie erwartet ist dadurch das Hinzufügen von Elementen recht schnell. Ein Contains prüft jedoch jedes einzelne Element in dem Stack wodurch auch die schlechte Performance erklärt wäre.

 

System.Collection.Generic in mscorlib

Der System.Collection.Generic namespace in der mscorlib enthält lediglich das generische Dictionary und die generische List (neben anderen Hilfsklassen und Interfaces).

Dictionary<TKey, TValue>

Dies ist wohl die am häufigsten verwendete Key-Value Datenstruktur. Dabei wird ein Hashwert des TKeys berechnet und zeigt auf einen Eintrag in einem zweiten Array. Sollte sich ein Hashwert doppeln so entsteht für diesen Eintrag eine einfach verkettete Liste, welche auf den nächsten Wert mit diesem Hash zeigt. In der Art funktioniert auch das ContainsKey: gestartet wird mit dem berechneten Hash und danach wird die Liste durchgegangen, bis das Objekt gefunden wurde oder keine weiteren Objekte mehr vorhanden sind. Auch wenn man sich nun vorstellen könnte, dass durch die Verwendung dieser Liste mehr als Int32 Elemente in dem Dictionary gehalten werden können so täuscht dies: da die eigentlichen Werte wiederum in einem Array von Werten (mit dem Zeiger auf den evtl. vorhanden nächsten Wert) gehalten werden so hat dies zur Folge, dass theoretisch bei 2.147.483.647 Einträgen Schluss ist.

List<T>

Der einzige Unterschied zwischen der generischen List und der ArrayList liegt in dem Typen. Die ArrayList hält intern ein Array von Object und die generische Liste vom Type T.

 

System.Collection.Generic in System.dll

Die generischen Collections in der System.dll sind zum größten Teil generische Varianten der bereits erwähnten Datenstrukturen. Somit erübrigt sich eine nähere Betrachtung der Queue<T>, SortedList<T> und Stack<T>.

LinkedList<T>

Diese Collection ist eine Implementierung einer ganz normalen doppelt verketteten Liste. Dadurch müssen jedoch für ein Contains oder Find alle Elemente durchsucht werden, welches wie erwartet natürlich einiges an Zeit beansprucht.

SortedDictionary<TKey, TValue>

Das SortedDictionary ist ein Rot-Schwarz Baum welcher die Warte speichert. Damit ist es beim Hinzufügen von Werten natürlich erheblich schneller als die SortedList.

 

1. Messung

Die erste Messung wurde mit 100.000 Einfüge-Operationen und 1000 Lookups durchgeführt.

Collection Einfügen Zeit in ms Lookup Zeit in ms Lookup Zeit in ms
ArrayList Add 80 BinarySearch 1    
Queue(NumOfItems) Enqueue 84 Contains 3879    
Queue Enqueue 97 Contains 2779    
Queue<String> Enqueue 100 Contains 4819    
Stack<String> Push 102 Contains 4041    
List<String> Add 103 BinarySearch 2    
Stack Push 107 Contains 2843    
LinkedList<String> AddFirst 120 Contains 6316    
HashSet<String> Add 131 Contains 0    
LinkedList<String> AddLast 134 Contains 5805    
ArrayList(NumOfItems) Add 151 BinarySearch 1    
Dictionary<String, String> Add 268 ContainsKey 0 ContainsValue 4577
Hashtable(NumOfItems) Add 285 ContainsKey 0 ContainsValue 8711
Hashtable Add 378 ContainsKey 0 ContainsValue 9602
ArrayList.Sort Add & Sort 383 BinarySearch 1    
SortedDictionary<String, String> Add 838 ContainsKey 3 ContainsValue 28380
ArrayList Insert(0) 10651 Contains 2655    
SortedList<String, String> Add 13602 ContainsKey 2 ContainsValue 6059
SortedList Add 13631 ContainsKey 1 ContainsValue 5906
SortedList(NumOfItems) Add 13734 ContainsKey 1 ContainsValue 5967

 

2. Messung

Die zweite Messung wurde mit 1.000.000 Einfüge-Operationen und 10.000 Lookups durchgeführt.

Collection Einfügen Zeit in ms Lookup Zeit in ms Lookup Zeit in ms
Stack<String> Push 1212 Contains 282.362    
ArrayList Add 1229 BinarySearch 19    
Stack Push 1234 Contains 264.446    
Queue<String> Enqueue 1249 Contains 265.460    
ArrayList(NumOfItems) Add 1318 BinarySearch 20    
Queue(NumOfItems) Enqueue 1380 Contains 254.415    
Queue Enqueue 1385 Contains 258.666    
LinkedList<String> AddFirst 1536 Contains 485.436    
List<String> Add 1587 BinarySearch 24    
LinkedList<String> AddLast 1676 Contains 557.289    
HashSet<String> Add 1858 Contains 0    
Dictionary<String, String> Add 3118 ContainsKey 0 ContainsValue 431.813
Hashtable Add 5267 ContainsKey 0 ContainsValue 917.237
ArrayList.Sort Add & Sort 5404 BinarySearch 20    
Hashtable(NumOfItems) Add 5444 ContainsKey 0 ContainsValue 833.834
SortedDictionary<String, String> Add 14.378 ContainsKey 40 ContainsValue 3.091.111
ArrayList Insert(0) 1.171.009 Contains 242.737    
SortedList Add 1.836.665 ContainsKey 19 ContainsValue 607.117
SortedList(NumOfItems) Add 1.838.737 ContainsKey 19 ContainsValue 622.087
SortedList<String, String> Add 1.845.453 ContainsKey 24 ContainsValue 671.537

 

Fazit

Sucht man eine Datenstruktur um Werte schnell zu speichern so ist die ArrayList die beste Wahl – vorausgesetzt man verwendet die Add Methode. Jedoch sollte unbedingt die BinarySearch Methode verwendet werden um Elemente zu laden oder auf deren Existenz zu prüfen. Steht jedoch die Suche nach Elementen im Vordergrund sollte lieber das HashSet<T> verwendet werden. Auch wenn dies durch die Berechnung des Hashwertes etwas langsamer beim Einfügen ist, so macht es dies bei einem Lookup wieder wett. Will man Key-Value Paare speichern, so ist das generische Dictionary<TKey, TValue>die erste Wahl.

Für sortierte Strukturen – will man keinen B* Baum implementieren – bietet sich das generische ArrayList mit der Sort() Methode an. Dieses ist für Einfügeoperationen am schnellsten und die Suche nach Elementen mit Hilfe der BinarySearch kann braucht sich nicht hinter dem SortedDictionary<TKey, TValue> zu verstecken.

VisualGraph – Eine sones GraphDB Visualisierung

Seit einiger Zeit geistert eine NoSQL Bewegung durchs Netz und Graphen Datenbanken sind zur Zeit in aller Munde (dicht gefolgt von den Clouds ;-) ). Doch wieso braucht man denn eigentlich eine Graphen Datenbank und wieso funktioniert das nicht so einfach mit den herkömmlichen relationalen DBMS? Dies soll das folgende Video verdeutlichen und Lust auf mehr machen. Wer mehr wissen will findet einige Informationen dazu unter www.sones.de wo man sich auch einen Test-Account anlegen und selber seine ersten Objekte in die Datenbank packen und miteinander verknüpfen kann.

Als Framework habe ich das OpenSource Graph-Layout-Framework GraphSharp verwendet. Dies machte es mir möglich in kurzer Zeit eine WPF Anwendung zu erstellen, welche die DBObjekte die direkt über die sones API aus der Datenbank selektiert werden, in einer Ansprechenden Form darzustellen.

 

.

C# Methoden Parameter

Wie verhält sich das eigentlich mit den Parametern von Methoden/Funktionen in C#? Wann werden eigentlich Referenzen von den Parametern übergeben, wann Kopien und vor allem: wann ändert sich das Objekt global?

Dies soll nun einmal geklärt werden!

Die Klasse MyTestClass ist lediglich eine Wrapper Klasse um ein Ojekt zu speichern und wird in allen Beipielen verwendet.

   1: class MyTestClass

   2: {

   3:     public Object AProperty { get; set; }

   4:     public override string ToString()

   5:     {

   6:         return AProperty.ToString();

   7:     }

   8: }

Standard Parameterübergabe

Zu erst einmal einen ganz normalen Methodenaufruf wie er wohl am häufigsten vorkommt:

   1: private void Start()

   2: {

   3:  

   4:     var param1 = "testParam";

   5:     var param2 = new MyTestClass() { AProperty = "testProperty" };

   6:  

   7:     MyVoid(param1, param2);

   8:  

   9:     Console.WriteLine("param1: " + param1);

  10:     Console.WriteLine("param2: " + param2);

  11: }

  12: public void MyVoid(String myParam1, MyTestClass myParam2)

  13: {

  14:     myParam1 = "inside MyVoid";

  15:     myParam2.AProperty = "inside MyVoid";

  16: }

Die Methode ändert intern den Inhalt des myParam1 Parameters, lässt jedoch das eigentlich Feld param1 unverändert. Dies liegt daran, dass die Speicheradresse durch die Zuweisung innerhalb der Methode geändert wird und dies somit keine Auswirkung auf den param1 Funktionsparameter hat. Anders bei der Instanz der Klasse MyTestClass in dem param2 Feld. Da die Speicheradresse die selbe bleibt ändert sich der Inhalt auch außerhalb der Methode. Das Ergebniss ist wie erwartet:

param1: testParam
param2: inside MyVoid

Parameterübergabe mit dem ref-Schlüsselwort

Das ref-Schlüsselwort bewirkt, dass die Referenz eines Objektes an die Methode übergeben wird. Im Gegensatz zu der ersten Methode kann somit auch die Speicheradresse der an die Methode übergebenen Parameter geändert werden. Somit wird auch für den String Parameter myParam1 der Inhalt verändert. Ein erneuter Aufruf der Funktion mit dem ref-Schlüsselwort.

   1: private void Start()

   2: {

   3:  

   4:     var param1 = "testParam";

   5:     var param2 = new MyTestClass() { AProperty = "testProperty" };

   6:  

   7:     MyVoid(ref param1, ref param2);

   8:  

   9:     Console.WriteLine("param1: " + param1);

  10:     Console.WriteLine("param2: " + param2);

  11: }

  12: public void MyVoid(ref String myParam1, ref MyTestClass myParam2)

  13: {

  14:     myParam1 = "inside MyVoid";

  15:     myParam2.AProperty = "inside MyVoid";

  16: }

Das Ergebnis ist:

param1: inside MyVoid
param2: inside MyVoid

Parameterübergabe mit dem out-Schlüsselwort

Das out-Schlüsselwort wird zur Kompilierzeit genauso gehandhabt wie das ref-Schlüsselwort. Der Unterschied ist jedoch, dass alle Parameter die mit out markiert sind innerhalb der Methode erst ein Wert zugewiesen werden muss, bevor diese verlassen werden kann. Das Ändern des Schlüsselwortes ref nach out erzeugt den Kompilierfehler “Use of unassigned out parameter ‘myParam2′”

Mit Linq eine List<List<String>> zu einer List<String> aggregieren

Linq ist eine tolle Sache und bietet einem die Möglichkeit mit wenig Zeilen vieles zu erledigen. Erst letztens bin ich wieder auf das Problem gestoßen, eine Liste von mehrere Listen in eine einzelne Liste zusammen zu führen:

   1: var l = new List<List<string>>();

   2:  

   3: l.Add(new List<string>(new[] { "a", "b", "c" }));

   4: l.Add(new List<string>(new[] { "d", "e", "f" }));

   5:  

   6: var newList = l.Aggregate((a, b) => { a.AddRange(b); return a; });

Das Resultat ist wie erwartet ein aggregierte Liste mit allen Elementen:

newList	Count = 6		System.Collections.Generic.List
		[0]	"a"	string
		[1]	"b"	string
		[2]	"c"	string
		[3]	"d"	string
		[4]	"e"	string
		[5]	"f"	string

Custom paging von ASP .Net Repeater controls

Das ASP .Net Framework ist zwar schon recht üppig ausgestattet, jedoch komme ich doch immer mal wieder an die Stelle, dass mir eine Funktion fehlt. So stellt das GridView Control eine super Paging Funktionalität zur Verfügung jedoch bei dem einfachen Repeater und DataList Control fehlt dieses. Da ich jedoch einfach nicht darauf verzichten will und kann musste ein Paging-Control her.

Das PagedDataSource von .Net ist zwar bereits ein guter Anfang jedoch fehlt das Rendern der Pages für das Front-End komplett. Diesem soll das Paging-Control Abhilfe schaffen. Die Verwendung ist denkbar einfach:

Als Beispiel soll eine Liste von Einträgen –gebunden an ein Repeater-Control – dienen. Diese werden in der Methode FetchData erzeugt und dem Repeater sowohl als auch dem Paging-Control als Information mitgegeben.

   1: private void FetchData(Int32 myCurrentPage)

   2: {

   3:     var data = new List<String>();          // Die Daten erzeugen

   4:     for (Int32 i = 0; i < 30; i++)

   5:         data.Add("Testentry " + i);

   6:  

   7:     ucPaging.DataSource = data;             // DataSource festlegen

   8:     ucPaging.CurrentPage = myCurrentPage;   // Aktuelle Seite setzen

   9:     ucPaging.DataSourceCount = data.Count;  // Anzahl der Elemente im Datasource setzen

  10:     ucPaging.DataBind();                    // Das Daten an das Control binden

  11:  

  12:     repData.DataSource = ucPaging;          // Dem Repeater das Paging-Control als DataSource

  13:     repData.DataBind();                     // übergeben

  14: }

C# Codebehind Datei

In der Page_Load Methode wird der URL Parameter “p” geprüft und falls er auf eine bestimmte Seite gesetzt wurde, an die FetchData Methode übergeben.

   1: protected void Page_Load(object sender, EventArgs e)

   2: {

   3:     Int32 curPage = 0;

   4:     if (Request.Params["p"] != null)

   5:         Int32.TryParse(Request.Params["p"], out curPage);

   6:     FetchData(curPage);

   7: }

C# Codebehind Datei

Die eigentliche .aspx Seite enthält zum einen natürlich das Repeater-Control und das Paging-Control:

   1: <uc:Paging ID="ucPaging" runat="server" PageSize="5">

   2:     <ActivePage>

   3:         < %# Container.PageNum+1 %>

   4:     </ActivePage>

   5:     <InactivePage>

   6:         <asp:HyperLink ID="lnkInactivePage2" runat="server" Text="<%# Container.PageNum+1 %>" NavigateUrl="<%# getUrl(Container.PageNum+1) %>" Visible="true"></asp:HyperLink>

   7:     </InactivePage>

   8: </uc:Paging>

   9: <br />

  10: <asp:Repeater ID="repData" runat="server">

  11:     <ItemTemplate>

  12:         < %#Container.DataItem %><br />

  13:     </ItemTemplate>

  14: </asp:Repeater>

Das Paging-Control bietet zwei Templates an, zum einen das ActivePage Template welches die Darstellung der aktiven Seite realisiert und dem InactivePage welches die inaktiven Seiten darstellt. In diesem Beispiel werden nur die inaktiven Seiten als Links dargestellt. Die Anzahl der Einträge pro Seite werden mit Hilfe der PageSize Eigenschaft angegeben. Die Methode getUrl generiert den darzustellenden Link an Hand der Seitennummer:

   1: public String getUrl(Int32 myPageNum)

   2: {

   3:     return "Default.aspx?p=" + (myPageNum-1);

   4: }

C# Codebehind Datei

Das Resultat sieht man hier:
1 2 3 4 5 6 Testentry 15 Testentry 16 Testentry 17 Testentry 18 Testentry 19

Den kompletten Quellcode inclusive des Paging-Controls kann man hier downloaden.

Ernst-Kohl-Straße Weimar

Der erste Artikel befasst sich wohl mehr mit einem Thema in einem begrenztem allgemeinen Interesse. Durch Zufall wurde ich darauf aufmerksam gemacht, dass ich gar nicht weiß, warum die Ernst-Kohl-Straße in Weimar so heißt, wie sie heißt. Nun ist es ja nicht unbedingt schlimm, wenn man keinen großartigen Bezug zu seiner Heimatadresse herstellt, aber mein Interesse war geweckt.

Wie üblich war der erste Weg natürlich Google und ich habe die Frage eigentlich schon als schnell erledigt abgestempelt – ein Trugschluss, wie sich herausstellen sollte. Es gab natürlich einige Treffer jedoch keinerlei nähere Informationen. Auch die Webseite Die Strassen von Weimar brachte keinen Erfolg – und dass es sich um eine mehr oder weniger berühmte Persönlichkeit handeln muss, war ja fast klar.

Ich hatte die ganze Angelegenheit schon fast wieder verdrängt, da bin ich durch Zufall bei einem Verwandten auf dieses Thema zu sprechen gekommen und er versprach, mir bei diesem Problem weiter zu helfen. Wenige Tage später erhielt ich dann den erlösenden Anruf:

Im Jahre 1875 wurde die heutige Ernst-Kohl-Straße das erste Mal nach “Kohl-Straße” umbenannt. Dies war zu Ehren von Ernst-Heinrich-Kohl, einem Eisenbahndirektor und Gemeinderatsmitglied in Weimar. Während der Zeit der DDR wurde sie zu Ehren der jungen Pioniere umbenannt um dann 1991 wieder zu dem bis jetzt gebliebenen Namen “Ernst-Kohl-Straße” zu wechseln. Wie es sich herausstellte, wurden in diesem Teil von Weimar einige weitere Straßen nach ehemaligen Gemeinderatsmitgliedern und Bürgermeistern benannt.

Dies alles ist nachzulesen Weimar. Straßen-, Platz- und Flurnamen damals und heute

Ringbinder theme by Themocracy