Archiv der Kategorie: C#

Neuronale Netze (KNN) / KI-Training: Das Format / der Aufbau vom MNIST-Datensatz (MNIST Datenbank) der Dateien t10k-images-idx3-ubyte, t10k-labels-idx1-ubyte, train-images-idx3-ubyte, train-labels-idx1-ubyte

Intention

Zum Auffrischen des eigenen Wissens über künstliche neuronale Netze (KNN) möchte man sich mit Frameworks wie PyTorch oder TensorFlow auseinandersetzen.

Problem

In den ersten Tutorials ist meistens die Rede vom „MNIST-Datensatz“ oder der „MNIST Datenbank“ mit 70.000 handgeschriebenen Ziffern im Format 28×28 mit 256 Grauwerten je Pixel (also je Byte). 60.000 Bilder davon sind zum Trainieren, 10.000 Bilder zum Testen eines neuronalen Netzes. Die Dateiendung der entpackten Dateien lässt sich nicht einfach in *.bmp umbenennen und zum Beispiel mit Paint öffnen. Man weiß erstmal nicht in welchem Format die Dateien sind um sich einzelne Zahlen anzusehen.

Laut „https://yann.lecun.com/exdb/mnist“ (manchmal nur über einen archive.org-Snapshot erreichbar) handelt es sich bei diesem Format nicht um ein Standard-Bildformat. Man muss ein eigenes Programm schreiben um diese Bilder zu interpretieren.

Analyse

train-images-idx3-ubyte, t10k-images-idx3-ubyte

Diese Dateien sind mit GZip (Endung *.gz) gepackt und lassen sich in Windows direkt mit einem Doppelklick öffnen oder mit einem Rechtsklick extrahieren:

Die *-images*-Dateien enthalten Bilder von handgeschriebenen Ziffern zwischen 0 und 9, die von Studenten und Mitarbeitern der Universität von South Carolina Beaufort im Jahre 1994 gesammelt wurden.

Öffnet man die extrahierten Dateien in einem Hexadezimaleditor wie zum Beispiel dem kostenlosen HxD-Editor und stellt die Spaltenanzahl auf 28 um, ist bereits ein Muster der enthaltenen Zahlen erkennbar:

Die ersten 16 Byte haben den folgenden Aufbau:

[offset] [type]          [value]          [description]
0000     32 bit integer  0x00000803(2051) magic number
0004     32 bit integer  60000            number of images
0008     32 bit integer  28               number of rows
0012     32 bit integer  28               number of columns
0016     unsigned byte   ??               pixel
0017     unsigned byte   ??               pixel
........
xxxx     unsigned byte   ??               pixel

Die 0x08 des dritten Bytes in der Magic Number sagt aus, dass es sich hierbei um UByte-Werte anhandelt. Das dritte Byte kann dabei die folgenden Werte annehmen:

The third byte codes the type of the data:
0x08: unsigned byte
0x09: signed byte
0x0B: short (2 bytes)
0x0C: int (4 bytes)
0x0D: float (4 bytes)
0x0E: double (8 bytes)

Das vierte Byte in der Magic Number hat hier den Wert 0x03, was bedeutet das unsere Daten 3 Dimensionen für den Pixel haben (x-Pos, y-Pos, Pixelwert/Grauwert[0-255]).

Entfernt man den markierten Header mit den ersten 16 Bytes (siehe obiges Bild) z.B. im HxD, indem man einfach die Entfernen-Taste drückt, ist das Schriftmuster bereits im HEX-Editor erkennbar:

Wie bereits erwähnt, hat jeder Pixel einen Wert zwischen 0 (weiß) und 255 (schwarz) [Magic Number: 3. Byte], wobei die Zwischenwerte lineare Abstufungen für Grauwerte sind.

Hier noch ein Beispiel der Fashion-MNIST-Datenbank mit Kleidungsstücken (von Zalando):

train-labels-idx1-ubyte, t10k-labels-idx1-ubyte

Der Aufbau der *-labels*-Dateien ist ähnlich. Als Label werden hier die Zahlen mit den Werten zwischen 0 bis 9 in der selben Reihenfolge wie in den *-images*-Dateien aufgeführt. Diese beginnen nach dem Header an Position 8 (hier 5 und 0 / unten wie oben im Screenshot):

Das Format ist also:

[offset] [type]         [value]          [description]
0000 32 bit integer 0x00000801(2049) magic number
0004 32 bit integer 60000 number of images
0008 byte [0-9] Ziffer zw. 0-9
……..

C#.NET: QR Code erzeugen mit QRCoder.dll / QR-Codes mit C# oder VB.NET erstellen / generieren

Beispiel: Kostenloser QR Code Generator

Hier ein kostenloser QR Code Generator, welcher in ASP.NET mit C# als Backend realisiert wurde:

https://www.my-asp-experiments.com/QRCode

Beschreibung

QRCoder ermöglicht das Erstellen von QR-Codes mit einer einfachen Bibliothek. Solange keine QR-Code-Version angegeben wird, passt sich die Größe der generierten QR-Codes an den zu codierenden Text an.

Die folgenden Parameter werden unterstützt:

  • ECC Level: Fehlerkorrekturlevel. Gibt an wieviel Redundanzen eingebaut werden um im Fehlerfalle trotzdem lesbare Q- Codes zu erhalten. Je höher der Level ist, desto weniger Text kann im QR-Code einer bestimmten Größe gespeichert werden. Es gibt 4 ECC-Level={L, M, Q, H}, die in der folgenden ENUM definiert sind:
    QRCodeGenerator.ECCLevel
  • Version (optional): Die QR-Code-Version legt eine feste Größe (Modulanzahl) für den generierten QR Code fest. Die QR-Code-Größe definiert sich durch die Anzahl der „Module“ in der Matrix. Ein „Module“ definiert ein Quadrat im QR-Code. Wird keine Version angegeben, vergrößert sich der QR-Code automatisch auf die entsprechende Version.
    Beispiele: Version 1 hat eine Größe von 21×21 Modulen, also 1(21×21), Version 2(25×25), 3(29×29), 4(33×33), 5(37×37), 6(41×41), 7(45×45), 8(49×49), 9(53×53), 10(57×57), 11(61×61) …
  • Pixel pro Modul: Die Anzahl der verwendeten Pixel für die Darstellung eines Moduls im QR-Code. Da Module im QR-Code quadratisch sind, gilt der Parameter für Breite und Höhe. Durch die exakte Festlegung der Pixel kann verhindert werden, dass der QR-Code wegen einer Skalierung unscharf oder verschwommen wird (wg. Aliasing).
  • Text (bzw. Textformat des zu codierenden Textes): Ein codierter Text kann numerische, alphanumerische, binäre oder Kanji-Zeichen enthalten. Die Reihenfolge dieser möglichen Zeichensätze legt von links nach rechts fest, wieviel Text insgesamt im QR-Code enthalten sein kann. Rein numerische Zeichen benötigen wenig Platz im QR-Code, wodurch für eine festgelegte Größe (Version) z.B. viel mehr Text codiert werden kann. Wenn ein Text aber nur ein einziges Kanji-Zeichen beinhaltet, wird der gesamte Textinhalt für Kanji codiert, was dazu führt dass weniger Text für eine Version (festgelegte Anzahl von Modulen) codiert werden kann.

Die folgende Tabelle verdeutlicht anhand der oben genannten Parameter, welche Datenkapazität (Textlänge) nach Version, ECC Level und verwendetem Zeichensatz erwartet werden kann:

Version (Modulzahl)NumerischAlphanumerischBinärKanji
LMQHLMQHLMQHLMQH
1(21)4134271725201610171411710874
2(25)7763483447382920322620142016128
3(29)1271017758776147355342322432262015
4(33)187149111821149067507862463448382821
5(37)255202144106154122876410684604465523727
6(41)32225517813919515410884134106745882654536
7(45)37029320715422417812593154122866495755339
8(49)46136525920227922115712219215210884118936652
9(53)552432312235335262189143230180130981411118060
10(57)6525133642883953112211742712131511191671319374
11(61)77260442733146836625920032125117713719815510985
12(65)88369148937453541929622736728720315522617712596
13(69)1022796580427619483352259425331241177262204149109
14(73)1101871621468667528376283458362258194282223159120
15(77)1250991703530758600426321520412292220320254180136
16(81)14081082775602854656470365586450322250361277198154
17(85)15481212876674938734531408644504364280397310224173
18(89)172513469487461046816574452718560394310442345243191
19(93)1903150010638131153909644493792624442338488384272208
20(97)2061160011599191249970702557858666482382528410297235
21(101)22321708122496913521035742587929711509403572438314248
22(105)2409187213581056146011348236401003779565439618480348270

Installation von QRCoder.dll

Die Bibliothek „QRCoder“ kann über die gängigen Quellen bezogen werden und muss dann ggfs. als Verweis hinzugefügt werden:


Einige der genannten Quellen tun dies allerdings automatisch

GitHub

https://github.com/codebude/QRCoder

.NET CLI

dotnet add package QRCoder --version 1.4.3

Package Manager

NuGet\Install-Package QRCoder -Version 1.4.3

Package Reference

<PackageReference Include="QRCoder" Version="1.4.3" />

Paket CLI

paket add QRCoder --version 1.4.3

Script & Interactive

#r "nuget: QRCoder, 1.4.3"

Cake

// Install QRCoder as a Cake Addin
#addin nuget:?package=QRCoder&version=1.4.3

// Install QRCoder as a Cake Tool
#tool nuget:?package=QRCoder&version=1.4.3

C# Konsolenanwendung

Die folgende C# Konsolenanwendung erzeugt drei QR-Codes der Version 5 (also 37×37 Module) mit dem Fehlerkorrekturlevel L (niedrigster Korrekturlevel für viel Platz) und 4×4 Pixel pro Modul. Der Text ist binär, da er die Sonderzeichen einer URL aber keine Kanji-Zeichen beinhaltet. Der erste QR-Code beinhaltet nur den Text „d“ und wird deswegen als alphanumerisch klassifziert.

Außerdem wird der „Ruhebereich“ des QR-Codes (weißer Rand) abgeschnitten, was nicht immer zu empfehlen ist, da diese Trennung für einen korrekten Scan benötigt wird.

using QRCoder;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QRCodeTestConsole
{
    public class Program
    {
        public static Program prg;
        public const int version5QRCodeSize = 148 + 32;
        public const int pixelPerModule = 4;
        public const int moduleVersion = 5;
        public const int croppedBorderPixels = 16; 
        public const QRCodeGenerator.ECCLevel eccLevel = QRCodeGenerator.ECCLevel.L;

        public Program()
        {
            string[] content = { "d", 
                                 "https://www.youtube.com/playlist?list=PLA4OWG_-fY-JLoj-bHIPiUU1SJquB9X8J",
                                 "https://www.youtube.com/playlist?list=PLA4OWG_-fY-JLoj-bHIPiUU1SJquB9X8J----------------------...........oipipoiopiopipoipiooipo"};
            
            for (int i = 0; i < content.Length; i++)
            {
                string current = content[i];              

                string msgResult = this.GenerateQRCode(current, "QRCode" + i + ".bmp");
                
                if (!msgResult.ToLower().Equals("ok"))
                {
                    Console.WriteLine(msgResult);
                }
            }

            Console.ReadLine();
        }

        public string GenerateQRCode(string content, string fileName)
        {
            try
            {
                QRCodeGenerator qrGenerator = new QRCodeGenerator();
                QRCodeData qrCodeData = qrGenerator.CreateQrCode(content, eccLevel, false, false, QRCodeGenerator.EciMode.Default, moduleVersion);
                QRCode qrCode = new QRCode(qrCodeData);
                Bitmap qrCodeImage = new Bitmap(qrCode.GetGraphic(pixelPerModule));

                // Ruhezone abschneiden - falls nicht 
                // gewünscht bei qrCodeImage.Save aufrufen 
                Bitmap croppedBmp = qrCodeImage.Clone(new Rectangle(croppedBorderPixels, croppedBorderPixels, qrCodeImage.Width - 2 * croppedBorderPixels, qrCodeImage.Height - 2 * croppedBorderPixels), qrCodeImage.PixelFormat);
                croppedBmp.Save("CROP_" + fileName);
            }
            catch (Exception e)
            {
                return e.ToString();
            }

            return "ok";
        }

        public static void Main(string[] args)
        {
            prg = new Program();
        }
    }
}

C# Threads: Was bedeutet „signaled“ beim AutoResetEvent-Konstruktor und im Kontext von AutoResetEvent?

Problemfeld

AutoResetEvent bietet über einen globalen oder übergeordneten Kontext die Möglichkeit durch den Aufruf der WaitOne-Methode innerhalb des Thread-Codes, Threads zu blockieren bis ein Signal aus einem anderem Kontext gesendet wird. Der andere Kontext sollte dabei auch Zugriff auf das steuernde AutoResetEvent-Objekt haben.

Konstruktor-Parameter

AutoResetEvent event_1 = new AutoResetEvent(true);
AutoResetEvent event_2 = new AutoResetEvent(false);

Ein Thread, welcher event_1.WaitOne() aufruft, blockiert nicht da signaled auf TRUE steht.

Ein Thread, welcher event_2.WaitOne() aufruft, blockiert da signaled über den Konstruktor mit FALSE initialisiert wurde.

Ruft ein Thread die Methode „WaitOne“ auf, wird dieser allerdings nur blockiert, wenn AutoResetEvent mit false initialisiert wurde.

Event auf „signaled“ ohne Konstruktor setzen

Um die blockierten Threads nun aus einem anderen Kontext, welcher auch Zugriff auf das AutoResetEvent-Objekt haben muss, zu steuern können die Methoden .Set() und .Reset() des AutoResetEvents aus dem steuerenden Kontext heraus genutzt werden:

// Setzt den Status auf "nicht signalisiert" / "non signaled" 
// Threads blockieren nach Aufruf von AutoResetEvent.WaitOne()
event_1.Reset(); 

// Setzt den Status auf "signalisiert" / "signaled"
// Threads blockieren NICHT nach Aufruf von AutoResetEvent.WaitOne()
event_2.Set(); 

Nur einer, der wartenden Threads erhält ein Signal wenn Set() aufgerufen wird. Will man alle wartenden Threads befreien, muss man Set() mehrfach aufrufen.

Unterschied zu ManualResetEvent

  • ManualResetEvent signalisiert allen wartenden Threads, dass diese die WaitOne()-Methode passieren dürfen. Sie ist also wie eine Tür, die sich für alle öffnet. ManualResetEvent.Reset(); schließt, die Tür, ManualResetEvent.Set(); öffnet die Tür.
  • AutoResetEvent signaliert maximal einem wartendendem Thread, dass er nach Aufruf der AutoResetEvent.WaitOne()-Methode weitermachen darf. Um alle blockierten Threads zu befreien, muss AutoResetEvent .Set() entsprechend der Anzahl wartender Threads aufgerufen werden. Wenn kein AutoResetEvent auf „signaled“ gesetzt wurde, wird auch niemand durchgelassen. Das entspricht der Warteschlange auf Ämtern oder Ärzten, wo man eine Nummer ziehen muss und immer nur einer aufgerufen wird.

WPF DataGrid MouseBinding Gesture List

Problem

The MouseBinding Tag in XAML is declaring a property „Gesture“, but it is hard to find a full reference / a complete list for all gestures of the MouseBinding tag.

Solution

Accepted gestures can be found in the enumeration MouseAction

LeftClick1A left mouse button click.
LeftDoubleClick5A left mouse button double-click.
MiddleClick3A middle mouse button click.
MiddleDoubleClick7A middle mouse button double-click.
None0No action.
RightClick2A right mouse button click.
RightDoubleClick6A right mouse button double-click.
WheelClick4A mouse wheel rotation.
List of possible gestures

C#.NET : Custom Collections anstelle von List erstellen über die mit foreach( … ) iteriert werden kann

Intention

Um die Klasse List<T> vor Zugriffen zu schützen / zu beschränken oder diese mit Notification-Events (z.B. ObservableCollection) auszustatten werden für den jeweiligen Verwendungszweck eigene Collections verwendet.

Ansatz

Um eine eigene Collection zu erstellen, welche mit foreach( … ) über die Elemente der eingekapselten Struktur (also z.B. List<T>) zu iterieren, benötigt man eine Enumerator-Klasse, welche die Methoden …

  • MoveNext()
  • Reset()
  • … und die Property „Current“ implementiert

implementiert (hier MyCollectionEnumerator) … sowie natürlich die gecustomizte Collection-Klasse selber, die die Datenstruktur enthält (hier MyCollection).

Lösung

using System;
using System.Collections.Generic;

namespace Irrsinn
{
    // Diese Klasse definiert mit MoveNext / Reset und der Property
    // Current aus dem Interface IEnumerator wie foreach(String s in col)
    // über die eingekapselte Liste iterieren darf.
    public class MyCollectionEnumerator : System.Collections.IEnumerator
    {
        private List<string> StringList;
        private int Counter = -1;

        // Im Konstruktor wird die Liste übergeben um die Operationen
        // MoveNext / Reset / Current darauf ausführen zu können
        public MyCollectionEnumerator(List<string> _StringList)
        {
            this.StringList = _StringList;
        }

        // Geht auf den nächsten Datensatz, der in der Liste 
        // gespeichert ist. Wenn MoveNext() false zurückgibt
        // ist das Ende der Liste erreicht
        public bool MoveNext()
        {
            Counter++;
            return Counter < StringList.Count;
        }

        // Setzt die Collection zurück.
        public void Reset()
        {
            Console.WriteLine("RESET!");
            Counter = -1;
        }

        // Gibt immer das aktuelle Element zurück, was mit 
        // MoveNext erreicht wurde
        public object Current
        {
            get
            {
                return StringList[Counter];
            }
        }
    }

    public class MyCollection
    {
        // Intern ist sind Collections meistens vom Typ List<T>
        // aber die eigene Implementierung gibt uns die Möglichkeit
        // den Zugriff auf die Liste anzupassen.
        private List<string> _StringList = new List<string>();

        // Hinzufügen eines Strings
        public void AddString(string newString)
        {
            this._StringList.Add(newString);
        }

        // GetEnumerator wird benötigt um mit foreach(...)
        // über die Collection zu iterieren
        public System.Collections.IEnumerator GetEnumerator()
        {
            return new MyCollectionEnumerator(_StringList);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Gecustomizte Collection
            MyCollection myCol = new MyCollection();
            myCol.AddString("Schatzi schenk mir ein Foto");
            myCol.AddString("schenk mir ein Foto vom Bier");
            myCol.AddString("Schatzi schenk mir ein Foto");
            myCol.AddString("Dann schenk ich Dir auch eins");
            myCol.AddString("vom Tier (also von den Muppets)");


            foreach (string s in myCol)
            {
                Console.WriteLine(s);
            }

            Console.ReadLine();
        }
    }
}

WPF MVVM: Was ist der Sinn hinter RelayCommand und wozu braucht man RelayCommand?

Problemfeld

RelayCommand (s) erfüllen den Zweck von Actions / Delegates und sind somit Funktionszeiger die es erlauben, zu einem späteren Zeitpunkt eine Methode aufzurufen.

Sie implementieren das Interface ICommand, welches von den WPF Controls genutzt wird, um bei Bedarf die Execute()-Methode aufzurufen. D.h. die Execute()-Methode soll nur dann aufgerufen werden, wenn das WPF Control das Ereignis tatsächlich auslöst und nicht bereits zur Bindung.

Ohne RelayCommands müsste man für jeden Command eine eigene Klasse schreiben, welche vom Interfache ICommand erbt. Sie helfen somit Code einzusparen.

Verwendung in einem MVVM Pattern

Häufige Verwendung: In einer XAML Datei wird ein Button definiert, der an einen RelayCommand gebunden wird, welcher zu einem späteren Zeitpunkt aufgerufen werden soll:

Das ViewModel, welches die View instanziert, muss einen RelayCommand „PerformCalibration“ definieren, der erst aufgerufen wird, wenn der Button geklickt wird (Relay) und nicht sofort bei der Bindung an den ButtonCommand.

Für diesen Zweck beinhaltet das ViewModel, welches die View instanziert, eine Funktion die den RelayCommand zurückgibt:
 

Der Button ruft die Funktion „Execute“ des implementierten RelayCommands auf, wenn er geklickt wird.

Da RelayCommands „Actions“ sind, haben Sie keinen Rückgabewert.

C# und Delegaten, Func, Action, Predicate

Was sind Delegates?

Beispiel:
public delegate string MeinDelegateName(string s);

Ein Delegate deklariert einen Datentyp (hier MeinDelegateName) anhand einer Funktionssignatur. Eine Funktionssignatur, welche den Aufbau einer Funktion darstellt, sieht folgendermaßen aus:

Rückgabewert DelegateName (Argumente)

Diesem Datentyp kann nun eine oder mehrere (siehe +=-Operator) Funktionen mit genau dieser Funktionssignatur zugewiesen werden, was das Aufrufen dieser Funktionen ermöglicht, ohne deren Namen zu kennen. Dadurch wird die Implementierung der Funktion von dem aufrufendem Code entkoppelt.

Ein Verwendungsbeispiel wären EventListener / Events, welchen über Delegates die Funktion übergeben wird, die beim Eintritt des Events aufgerufen werden soll. Über den += Operator können einem Event mehrere Funktionen zugewiesen werden (z.B. bei einem Windows-Fenster das OnLoad-Event).

Bei der Verwendung von Delegates muss also der Delegate-empfangende Code den Namen der Funktion (bzw. Methode) nicht wissen und kann diese trotzdem aufrufen. Delegates anonymisieren also Funktions- bzw. Methodennamen. Ein ähnlicher Mechanismus für Klassen stellen Interfaces zur Verfügung. Interfaces anonymisieren allerdings nicht per se Namen der deklarierten Methoden/Funktionen sondern lediglich der Klassennamen. Wäre eine Anonymisierung von Funktions- und Methodennamen gewünscht, könnten die Delegates in den Interfaces deklariert werden.

Deklaration von Delegate-Typen mit dem normalen Delegate-Schlüsselwort

// Definition des Delegatentyps SageHalloWeltDelegate:  
// Eine Funktionssignatur, welcher ein string übergeben
// wird und welche einen String zurückgibt, wird festgelegt
public delegate string SageHalloWeltDelegate(string s); 

public string sageHalloWeltFunktion(string s)
{
    Console.Write("Hallo");
    return " Welt";
}

public Program()
{
    // Instanz der Funktion "delegateInstanzDerFkt" mit der 
    // Funktionssignatur "SageHalloWeltDelegate"
    SageHalloWeltDelegate delegateInstanzDerFkt = sageHalloWeltFunktion;
    
    // Aufruf der instanzierten Funktion 
    Console.WriteLine(delegateInstanzDerFkt("Hallo"));		
}

Durch .NET vordefinierte Delegattypen: Action / Func / Predicate

 .NET enthält jedoch eine Reihe von Delegattypen, die Programmierer verwenden können, damit sie keine neuen Typen (wie oben der Typ „SageHalloWeltDelegate„) erstellen müssen. Diese Typen lauten Func<>Action<> und Predicate<>

Die Deklarationszeile des Delegate-Typs
public delegate string SageHalloWeltDelegate(string s);
fällt somit weg.

  • Action<> wird verwendet, wenn eine Aktion mithilfe der Argumente des Delegaten ausgeführt werden muss. Die von dem Typ gekapselte Methode gibt keinen Wert zurück.
    Die Signatur darf maximal 16 Argumente enthalten.

    Bsp. für eine Action
    Action<string> delegateInstanzDerFkt = sageHalloWeltFunktion;

    Hier würde der Teil “ Welt“ aus dem obigen Beispiel nicht zurückgegeben werden.
  • Func<> wird üblicherweise verwendet, wenn eine Transformation ausgeführt werden muss, Sie also die Argumente des Delegaten in ein anderes Ergebnis transformieren müssen. Projektionen sind ein gutes Beispiel. Die von dem Typ gekapselte Methode gibt einen angegebenen Wert zurück.
    Die Signatur darf maximal 16 Argumente enthalten.

    Bsp. für Rückgabewert „string“ und Übergabewert „string“:
    Func<string, string> delegateInstanzDerFkt = sageHalloWeltFunktion;

    Der letzte Typparameter der Func-Deklaration ist jeweils der Rückgabewert.
    Func<string, string, int> delegateInstanzDerFkt = sageHalloWeltFunktion;
    würde einen Integer-Wert zurückgeben und ihr würden zwei Strings übergeben werden.
  • Predicate<> wird verwendet, wenn Sie ermitteln müssen, ob das Argument die Bedingung des Delegaten erfüllt. Sie können auch die Schreibweise Func<T, bool> verwenden. In diesem Fall gibt die Methode einen booleschen Wert zurück.
    Predicates werden meistens bei LINQ verwendet, wenn man zum Beispiel in Collections oder Listen etwas suchen möchte. Meistens wird Predicate dann als LAMBDA-Ausdruck geschrieben.
    Die Signatur darf maximal 16 Argumente enthalten.

    Func<string, bool> delegateInstanzDerFkt = sageHalloWeltFunktion;
    ist also äquivalent mit
    Predicate<string> delegateInstanzDerFkt = sageHalloWeltFunktion;
    und würde mit dem obigen Beispiel zu einem Fehler führen, da die Methode sageHalloWeltFunktion einen String zurückgibt.

Konvertieren von Lamda-Ausrücken in Delegateinstanzen

// Berechne quadrat
Func<int, int> square = x => x * x; 
Console.WriteLine(square(5));

// Konkateniere String
Func<string, string, string> concat = (a,b) => a + " " + b;
concat("Hello", "World");

// Einzelne Action wird ohne Übergabeparameter (Rückgabe hat sie nicht)
Action line = () => Console.WriteLine("Hello world!");
line();

// Einzelne Action wird ohne Übergabeparameter (Rückgabe hat sie nicht)
Action line = text => Console.WriteLine(text);
line("Hello world!");

Example:

Visual Studio 2013 : Show folders with *.cs files in the solution explorer after they suddenly disappeared / hidden

Problem

Sometimes it happens, that you have created folders in Visual Studio for your application and had put some *.cs C# Source Code files that suddenly disappeard in the solution explorer.

Analysis

I.e. that can happen when you have forgotten to save your Visual Studio application project, berfore you have closed the IDE.

Solution

Use the file explorer and navigate to your Visual Studio solution (alternatively you can right-click a source code file in your folder and select „Open contained folder“ from the context menu).

Open the .csproj file in your solution in a text editor of your choice:

.csproj files store the project structure of the solution explorer

Go to the section where the <ItemGroup /> tags are declared and add a new section with the folders and source code files you want to show in your solution like in the screenshot below

My folders Command, ViewModelBase, ViewModel and Model disappeard over night, so i readded the marked group

You can add all cs-files with a wildcard star like it is shown in the screenshot above.

C# .NET : Collections im .NET Framework

Intention

Eines der wichtigsten .NET Elemente zum Verwalten vom Datenbeständen im Speicher sind Collections (Auflistungen). Im Vergleich zu normalen Array-Typen bieten diese die Möglichkeit zur Laufzeit Objekte hinzuzufügen, ohne vorher die Größe/die Anzahl der Objekte in der Collection zu kennen. Collections bieten Funktionen zum Hinzufügen, Entfernen und Suchen/Finden von Objekten. Ist ein Objekt in einer Auflistung erstmal gefunden, kann dieses über die Objektreferenz auch direkt in der Auflistung geändert werden.

Typsicher
  • Bessere Leistung
  • keine explizite Umwandlung notwendig um auf Objekteigenschaften zuzugreifen
  • Akzeptieren beim Erstellen einen Typparamter <T>
  • Unterstützung für Windows-Store-Apps
Typsicher…
Generische Auflistungen
Generische Auflistun…
Nicht
generische Auflistungen
Nicht…
Auflistungen
(Collections)
Auflistungen…
Nicht typsicher
  • Speichern Elemente als Objekt (Object)
  • erfordern explizite Umwandlung in den Objekttyp um auf Objekteigenschaften zuzugreifen
  • keine Unterstützung für Windows-Store-Apps
Nicht typsicher…
System.Collections.Concurrent
System.Collections.Concurrent
System.Collections
System.Collections
System.Array
System.Array
System.Collections.Generic
System.Collections.Generic
Threadsicher
Threadsicher
Findet man oft in älterem Code
Findet man oft…
System.Collections.Immutable
System.Collections.Immutable
NuGet-Paket
NuGet-Paket
Actor
Actor
Hinzufügen
Hinzufügen
Ändern
Ändern
Entfernen
Entfernen
Suchen
Suchen
        Collection
  1. Object 1
  2. Object 2
  3. Object 3
  4. Object n
Collectio…
«interface»
 System.Collections.IEnumerable
«interface»…
foreach(Object o in Collection) 
{
  o.Property…
}
foreach(Object o in Collectio…
«interface»
 System.Collections.Generic.IEnumerable
«interface»…
LINQ
var
query = from Object o in Collection
where o.Attribute > 95
select o;

foreach (Object o in query) {
Console.WriteLine(o.Attribute + „“
);
}
LINQ…
Viewer does not support full SVG 1.1

Auflistungen implementieren das Interface „IEnumerable“, um das Iterieren durch die Objekte in der Liste zu ermöglichen. Die foreach-Schleife nutzt beispielsweise dieses Interface um durch alle Objekte einer Collection zu iterieren.

Über die Abfragesprache LINQ (Language Integrated Query) lassen sich SQL-ähnliche Abfragen auf Collections durchführen,

Namespaces / Namensräume

Der Namensraum für .NET Framework Collections liegt unter System.Collections.*, wobei weitere Sub-Namensräume existieren.

  • System.Collections.Concurrent (mehrere Threads / Tasks können parallel auf diesen Collections im Speicher operieren)
  • System.Collections.Immutable (man arbeitet hierbei nur auf Kopien / die ursprünglichen Daten werden nicht geändert – muss zusätzlich über NuGet-Paket installiert werden)
  • System.Collections.Generic

Dynamische Strukturen/Collections allokieren immer 2^n Speicher-Plätze

Die Property „Capacity“, welche an jeder Collection anhängt, zeigt die Anzahl der Speicherplätze, die die Collection intern als Array alloziert hat. Bei 1025 Elementen werden intern 2048 Plätze vorbereitet. Bei 2049 Elementen werden intern 4096 Plätze vorbereitet.

C# + Reguläre Ausdrücke / Regular Expressions / Progress Tags : Alle Vorkommnisse zwischen einem Start-Teilstring und End-Teilstring (z.B. bei HTML Tags) finden und verarbeiten / Find all occurencies of start and end tag and progress them

Problem

Es sollen alle Vorkommnisse eine Start- und End-Tags gefunden werden und der Text dazwischen verarbeitet werden.

Ansatz – Approach

Verwendung von regulären Ausdrücken:

Regex.Matches findet alle Auftreten anhand eines Patterns, was den Regulären Ausdruck definiert:

(diagram://{[^>]+})

Eine Funktion string replaceDiagramAndElementLinkURLs(string eaNoteString) baut einen neuen String zusammen und schickt ihr wieder zurück.

Lösung – Solution

Im folgenden Beispiel gibt es in einem String mehrere Vorkommnisse des Start-Tags „$diagram://{“ und dem End-Tag „}“.
Zwischen dem Diagramm steht eine Nummer (guid) die an eine aspx-Seite übergeben werden soll.

Z.B. lautet der String

string verarbeiten = @"
<html>
...
Dies ist ein Diagramm: <a href="$diagram://{1234465}">Link 1</a> hier steht noch 
ein Diagramm: <a href="$diagram://{3455565}">Link 2</a> und das führt sich fort..
...
</html>
";

und nach dem Verarbeiten ist der Inhalt:

string verarbeiten = @"
<html>
...
Dies ist ein Diagramm: <a href="Level2Process.aspx?map=1234465">Link 1</a> hier steht noch 
ein Diagramm: <a href="Level2Process.aspx?map=3455565">Link 2</a> und das führt sich fort..
...
</html>
";

Dazu kann man folgenden Regulären Ausdruck verwenden:

    public static string replaceDiagramAndElementLinkURLs(string eaNoteString)
    {
        string neuerString = eaNoteString;
        string pattern = @"(diagram://{[^>]+})";

        MatchCollection matches = Regex.Matches(neuerString, pattern);

        if (matches.Count > 0)
        {
            foreach (Match m in matches)
            {
                string toReplace = "$" + m.Groups[1].ToString();
                string guid = toReplace.ToString().Replace("$diagram://", "");

                neuerString = neuerString.Replace(toReplace, "Level2Process.aspx?map="+guid );
            }
        }
        return neuerString;
}