diff --git a/01-3 TestPersonalausweis/UnitTest1.cs b/01-3 TestPersonalausweis/UnitTest1.cs
index b81f42a96decf348ac7589af07d752643aa90417..78f2c78d05da71cdf88d73f01821fc41d62c7e78 100644
--- a/01-3 TestPersonalausweis/UnitTest1.cs	
+++ b/01-3 TestPersonalausweis/UnitTest1.cs	
@@ -23,7 +23,7 @@ namespace _01_3_TestPersonalausweis
             Personalausweis perso = new Personalausweis("Anton");
             Assert.Equal(1001, Personalausweis.NaechsteID);
         }
-    }
+    } 
     public class TestKlasseBuergeramt
     {
     }
diff --git a/02-4 VerketteteStrukturenIntro/Liste.cs b/02-4 VerketteteStrukturenIntro/Liste.cs
index 0b68013f4ad5e158cd1ee861bc29519e62fb9b0b..0daec7f87f1b43a633a9aa7a93410aa4c1a8ae26 100644
--- a/02-4 VerketteteStrukturenIntro/Liste.cs	
+++ b/02-4 VerketteteStrukturenIntro/Liste.cs	
@@ -105,6 +105,9 @@ namespace _02_4_VerketteteStrukturenIntro
 
         public void DeleteFirst()
         {
+            // 1.Fall: Liste ist leer
+            // 2.Fall: Liste besteht nur aus einem Element
+            // 3.Fall: Liste hat mehr als ein Element
             if (anz == 0)
                 return;
 
diff --git a/04-1 VerketteteStrukturen2/04-1 VerketteteStrukturen2.csproj b/04-1 VerketteteStrukturen2/04-1 VerketteteStrukturen2.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..4f4a301a522c4ba4f25e42397f9f0e0f8862e2c9
--- /dev/null
+++ b/04-1 VerketteteStrukturen2/04-1 VerketteteStrukturen2.csproj	
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <RootNamespace>_04_1_VerketteteStrukturen2</RootNamespace>
+  </PropertyGroup>
+
+</Project>
diff --git a/04-1 VerketteteStrukturen2/Program.cs b/04-1 VerketteteStrukturen2/Program.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1266a093997e99c6c4dac51d9b9c435f40007339
--- /dev/null
+++ b/04-1 VerketteteStrukturen2/Program.cs	
@@ -0,0 +1,21 @@
+using System;
+
+namespace _04_1_VerketteteStrukturen2
+{
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            StringListe l1 = new StringListe();
+
+            l1.AddSorted("Emil ");
+            l1.AddSorted("Anton");
+            l1.AddSorted("Berta");
+            l1.AddSorted("Claudia");
+            l1.AddSorted("Dieter");
+
+            foreach (var item in l1.Filter("er"))
+                Console.WriteLine(item);
+        }
+    }
+}
diff --git a/04-1 VerketteteStrukturen2/StringListe.cs b/04-1 VerketteteStrukturen2/StringListe.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2c850959a6a17ff04aa6eaf3dfea75ef68d9b7ed
--- /dev/null
+++ b/04-1 VerketteteStrukturen2/StringListe.cs	
@@ -0,0 +1,217 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace _04_1_VerketteteStrukturen2
+{
+    class StringListe
+    {
+        #region Hilfsklasse für das einzelne Listenelement
+        // Die Klasse Element ist  eine *private* Klasse der Klasse StringListe
+        // Die Methoden von StringListe dürfen auf private Member zugreifen
+        // Methoden außerhalb von StringListe dürfen dies nicht!
+        private class Element  // Element ist eine private Hilfsklasse der Klasse StringListe
+        {
+            public string name;
+            public Element next = null;
+            public Element(string name) { this.name = name; }
+            public override string ToString() => name;
+        }
+        #endregion
+
+        Element anf = null, ende = null;
+        int anz = 0;      // Sehr sinnvoll für Index-Ops
+
+        #region Elemente aufzählen
+        public IEnumerator<string> GetEnumerator()
+        {
+            for (Element item = anf; item != null; item = item.next)
+            {
+                yield return item.name; // Merken dieser Ausführungsposition
+                                        // UND Zurückliefern von item.name
+                                        // Beim nächsten Aufruf von GetEnumerator() wird
+                                        // an der gespeicherten Pos. weitergemacht.
+            }
+        }
+        // GetEnumerator() --> IEnumerator
+        // alle anderen    --> IEnumerable
+        public IEnumerable<string> Filter(string text)
+        {
+            for (Element item = anf; item != null; item = item.next)
+            {
+                if (item.name.Contains(text))
+                    yield return item.name; 
+            }
+        }
+        #endregion
+
+        #region Elemente hinzufügen
+        public void AddEnd(string name)
+        {
+            Element neuesElement = new Element(name);   // 1. Neues Element anlegen
+            anz++;
+            if (anf == null)                            // 2. Leere Liste?
+                anf = ende = neuesElement;
+            else
+            {
+                ende.next = neuesElement;               // 3. Neues Element am Ende anfügen
+                ende = ende.next;
+            }
+        }
+        public void AddFront(string name)
+        {
+            // 1. Leere Liste
+            // 2. Es existiert mind. ein Element
+            Element neuesElement = new Element(name);   // Neues Element anlegen
+            anz++;
+            if (anf == null)                            // 1.Fall: Leere Liste?
+                anf = ende = neuesElement;
+            else
+            {
+                neuesElement.next = anf;                // 2. Fall
+                anf = neuesElement;
+            }
+        }
+        public void AddBeforeNth(int index, string name)
+        {
+            if (index < 0 || index > anz)
+                throw new ArgumentOutOfRangeException("Index außerhalb der Liste");
+            if (index == 0)
+                AddFront(name);
+            else if (index == anz)
+                AddEnd(name);
+            else
+            {
+                Element neu = new Element(name);
+                anz++;
+                Element item = anf;
+                for (int i = 1; i < index; i++)
+                    item = item.next;
+                neu.next = item.next;    // Die Reihenfolge dieses und des nächsten Befehls ist ENTSCHEIDEND!
+                item.next = neu;
+            }
+        }
+        public void AddSorted(string name)
+        {
+            // Fall 1: Leere Liste
+            // Fall 2: Anfügen am Listenende
+            // Fall 3: Einfügen am Listenanfang
+            // Fall 4: Einfügen mittendrin
+
+            // a.CompareTo(b) => neg. gdw. a <  b       eigentlich a-b
+            //                => 0    gdw. a == b
+            //                => pos. gdw. a >  b
+
+            if (anf == null || ende.name.CompareTo(name) <= 0)  // ende.name < name?
+                AddEnd(name);
+            else if (name.CompareTo(anf.name) <= 0)
+                AddFront(name);
+            else
+            {
+                // Hier wissen wir:
+                // Das neue Element ist nicht das erste und nicht das letzte Element
+                Element neu = new Element(name);
+                anz++;
+
+                Element item = anf;
+                while (item.next.name.CompareTo(name) < 0)
+                    item = item.next;
+                // Findet dasjenige Element, dessen Nachfolgername erstmalig größer
+                // als der Name des neuen Elements ist; Hier: item = "A", item.next = "C"
+                neu.next = item.next; // "C"
+                item.next = neu;
+            }
+        }
+        #endregion
+
+        #region Elemente löschen
+        public void DeleteFirst()
+        {
+            // 1.Fall: Liste ist leer
+            // 2.Fall: Liste besteht nur aus einem Element
+            // 3.Fall: Liste hat mehr als ein Element
+            if (anz == 0)
+                return;
+
+            anz--;
+            if (anz == 0)
+                anf = ende = null;
+            else // Wir wissen: Die Liste enthält MEHR als ein Element!
+                anf = anf.next;
+        }
+        public void DeleteLast()
+        {
+            // 1.Fall: Liste ist leer
+            // 2.Fall: Liste besteht nur aus einem Element
+            // 3.Fall: Liste hat mehr als ein Element
+            if (anz == 0)       // Fall 1
+                return;
+
+            anz--;
+            if (anz == 0)       // Fall 2
+                anf = ende = null;
+            else // Wir wissen: Die Liste enthält MEHR als ein Element!
+            // d.h. es gibt ein vorletztes Element mit vorletzter.next == ende
+            {
+                Element vorletzter = anf;
+                while (vorletzter.next != ende)
+                    vorletzter = vorletzter.next;
+
+                vorletzter.next = null;
+                ende = vorletzter;
+            }
+        }
+        public void DeleteNth(int index)
+        {
+            // 1.Fall: Liste ist leer ODER Ind>=anz --> Fehler
+            // 2.Fall: Ind == 0  --> DeleteFirst
+            // 3.Fall: Ind == anz-1 --> DeleteLast
+            // 4. Bis hierher: Liste hat mind. ein Element und das zu löschende Element
+            //                 ist nicht das Erste oder Letzte
+            if (anz == 0 || index >= anz)  // 1. Fall
+                throw new ArgumentOutOfRangeException("Außerhalb der Anzahl der Listenelemente");
+            if (index == 0)  // 2. Fall
+                DeleteFirst();
+            else if (index == anz - 1) // 3. Fall
+                DeleteLast();
+            else
+            {
+                Element vorletzter = anf;
+                for (int i = 0; i < index - 1; i++)  // Liste bis zum n-1-ten Element durchlaufen
+                    vorletzter = vorletzter.next;
+                vorletzter.next = vorletzter.next.next;
+                anz--;
+            }
+        }
+        public void DeleteByName(string DelName)
+        {
+            // Fall 1: leere Liste
+            // Fall 2: Erstes Element soll gelöscht werden
+            // Fall 3: Ein Element außer dem ersten soll gelöscht werden
+            // Fall 4: Das zu löschende Element ist das letzte Element
+
+            if (anf == null)  // Fall 1
+                return;
+            if (anf.name.CompareTo(DelName) == 0)  // Fall 2
+                DeleteFirst();
+            else
+            {
+                // Wir wissen jetzt:
+                // Liste hat mindestens ein Element UND das erste Element ist nicht das gesuchte Element!!!
+                Element vorletzter = anf;
+                while (vorletzter.next != null && vorletzter.next.name.CompareTo(DelName) != 0)
+                    vorletzter = vorletzter.next;
+
+                if (vorletzter.next != null)    // Gesuchtes Element gefunden!
+                {
+                    anz--;
+                    vorletzter.next = vorletzter.next.next;
+                    // d.h. nächstes Element wird übersprungen, d.h. gelöscht
+                }
+                if (vorletzter.next == null)        // Fall 4
+                    ende = vorletzter;
+            }
+        }
+        #endregion
+    }
+}
diff --git a/04-UbgListe-Mo/04-UbgListe-Mo.csproj b/04-UbgListe-Mo/04-UbgListe-Mo.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..6045e4164a5e2e6c2fe0aea44a4be11562868f7e
--- /dev/null
+++ b/04-UbgListe-Mo/04-UbgListe-Mo.csproj
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <RootNamespace>_04_UbgListe_Mo</RootNamespace>
+  </PropertyGroup>
+
+</Project>
diff --git a/04-UbgListe-Mo/Program.cs b/04-UbgListe-Mo/Program.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d57e0ed92cb73ecf2f2a9d2bc2321969435156fc
--- /dev/null
+++ b/04-UbgListe-Mo/Program.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace _04_UbgListe_Mo
+{
+    class Program
+    {
+        // Erstellen Sie eine ToDo-Liste
+        // Nutzlast: string toDo
+        // Geschachtelte Klassen
+        // Operationen:
+        // void Add() - Anfügen am Ende
+        // string[] GetAll() - Alle Listenelemente in einem Feld zurückgeben
+        // GetEnumerator()
+        // Indexer this[int ind]
+        // Indexer this[string s]; Contains() kann genutzt werden
+
+        static void Main(string[] args)
+        {
+            ToDoListe todos = new ToDoListe();
+            todos.Add("Milch einkaufen");
+            todos.Add("Praktikumsaufgabe bearbeiten");
+
+            string[] aufgaben = todos.GetAll();
+            todos[1] = "Praktikumsaufgabe bewerten";
+
+            foreach (string item in todos)
+                Console.WriteLine(item);
+
+            Console.WriteLine(todos["wert"]);
+        }
+    }
+}
diff --git a/04-UbgListe-Mo/ToDoListe.cs b/04-UbgListe-Mo/ToDoListe.cs
new file mode 100644
index 0000000000000000000000000000000000000000..33710e0cc7b04fe96dc7c36eac5dbe0c4f8ede02
--- /dev/null
+++ b/04-UbgListe-Mo/ToDoListe.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace _04_UbgListe_Mo
+{
+    class ToDoListe
+    {
+        /* private */ class ToDoItem
+        {
+            public string todo;
+            public ToDoItem next;
+            public ToDoItem(string s) { todo = s; next = null; }
+        }
+
+        ToDoItem first = null, last = null;
+        int count = 0;
+
+        public void Add(string ToDo)
+        {
+            // Fall 1: Liste ist leer
+            // Fall 2: Liste besitzt schon Elemente
+
+            ToDoItem newItem = new ToDoItem(ToDo);
+            count++;
+
+            if (first == null)
+                first = last = newItem;  // Fall 1
+            else
+            {                            // Fall 2
+                last.next = newItem;
+                last = newItem;
+            }
+        }
+        //public string[] GetAll()
+        //{
+        //    string[] res = new string[count];
+        //    int x = 0;
+
+        //    for (ToDoItem item = first; item != null; item = item.next)
+        //        res[x++] = item.todo;
+        //    return res;
+        //}
+        public IEnumerator<string> GetEnumerator()
+        {
+            for (ToDoItem item = first; item != null; item = item.next)
+                yield return item.todo;
+        }
+        public string[] GetAll()
+        {
+            string[] res = new string[count];
+            int x = 0;
+
+            foreach (string item in this)
+                res[x++] = item;
+            return res;
+        }
+
+        private ToDoItem ElementN(int ind)
+        {
+            ToDoItem item = first;
+            for (int i = 0; i < ind; i++)
+                item = item.next;
+            return item;
+        }
+        public string this[int ind]
+        {
+            get => ElementN(ind).todo;
+            //{
+            //    ToDoItem item = ElementN(ind);
+            //    return item.todo;
+            //}
+            set
+            {
+                //ToDoItem item = ElementN(ind);
+                //item.todo = value;
+                ElementN(ind).todo = value;
+            }
+        }
+        private ToDoItem FindText(string text)
+        {
+            for (ToDoItem item = first; item != null; item = item.next)
+                if (item.todo.Contains(text))
+                    return item;
+            return null;
+        }
+        public string this[string text]
+        {
+            get => FindText(text).todo;
+            
+            set
+            {
+                FindText(text).todo = value;
+            }
+        }
+    }
+}
diff --git a/Prog2WienkopSS2021.sln b/Prog2WienkopSS2021.sln
index 0d2b9d0b8a8174335ee5483b9fb96b1530447e6b..70c4c38c37a4851adaa0be876b5ed0e008728af0 100644
--- a/Prog2WienkopSS2021.sln
+++ b/Prog2WienkopSS2021.sln
@@ -21,7 +21,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-4 VerketteteStrukturenIn
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-UbgKlasseTime-Mo", "03-UbgKlasseTime-Mo\03-UbgKlasseTime-Mo.csproj", "{DD51B164-0F20-47B9-94C4-549CE555DDC2}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "03-UbgListe-Di", "03-UbgListe-Di\03-UbgListe-Di.csproj", "{0E5C379D-0D10-4CAC-A12C-4757DE1E5C4E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-UbgListe-Di", "03-UbgListe-Di\03-UbgListe-Di.csproj", "{0E5C379D-0D10-4CAC-A12C-4757DE1E5C4E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "04-UbgListe-Mo", "04-UbgListe-Mo\04-UbgListe-Mo.csproj", "{A2BD08A7-3354-4A7E-A80E-8344C2D22F50}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "04-1 VerketteteStrukturen2", "04-1 VerketteteStrukturen2\04-1 VerketteteStrukturen2.csproj", "{87021F69-DA51-4CA6-8394-C8819675D893}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -69,6 +73,14 @@ Global
 		{0E5C379D-0D10-4CAC-A12C-4757DE1E5C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{0E5C379D-0D10-4CAC-A12C-4757DE1E5C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{0E5C379D-0D10-4CAC-A12C-4757DE1E5C4E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A2BD08A7-3354-4A7E-A80E-8344C2D22F50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A2BD08A7-3354-4A7E-A80E-8344C2D22F50}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A2BD08A7-3354-4A7E-A80E-8344C2D22F50}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A2BD08A7-3354-4A7E-A80E-8344C2D22F50}.Release|Any CPU.Build.0 = Release|Any CPU
+		{87021F69-DA51-4CA6-8394-C8819675D893}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{87021F69-DA51-4CA6-8394-C8819675D893}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{87021F69-DA51-4CA6-8394-C8819675D893}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{87021F69-DA51-4CA6-8394-C8819675D893}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE