Archiv der Kategorie: C#

Meine lieblings C# 6 Sprachfeatures


Man freut sich immer darüber wenn C# neue Features hinzugefügt werden und hofft das man so viele wie möglich davon auch verwenden wird, denn die meisten vereinfachen einem das Programmieren und sparen Codezeilen ein. Außerdem kann man die neuen Features auch in älteren Projekten verwenden, wichtig ist nur das VS 2015 oder TFS 2015 für das Bauen der Projekte verwendet wird, denn es handelt sich um reine Compiler Features und nicht um Features die durch eine neue .NET Version eingeführt wurden. Aktuell verwende ich die folgenden neuen Features recht häufig, was in vielen Fällen meiner Meinung nach die Lesbarkeit des Codes klar verbessert.

1. String Interpolation anstatt String.Format

Wenn man ein “$” Zeichen vor einen String schreibt den man erstellen möchte kann man im String selbst mit Hilfe von “{varname}” geschweiften Klammern direkt auf Variablen zugreifen. Was wesentlich angenehmer ist wie String.Format, wo man jedes mal nachzählen musste ob man auch den Wert an der richtigen Stelle einfügt.

2. nameof Schlüsselwort

Mit Hilfe des nameof Schlüsselworts, bekommt man die Bezeichnung eines beliebigen Properties zurück was man übergibt. Dies was früher maximal durch Reflexion möglich oder in dem man einen String mit dem Namen selbst angelegt hat. Jetzt reicht dafür ein einfacher Aufruf aus.

3. Direktes Initialisieren von Properties ohne Konstruktor

In vielen einfachen Klassen initialisiere ich die Properties jetzt direkt ohne das ich einen Konstruktor verwende, was die Klasse kleiner macht und wie ich finde übersichtlicher, da man direkt sieht mit welchem Wert in Property initialisiert wird.

4. Elvis Operator “?” in Verkettungen

Die Verwendung des Fragezeichens “?” direkt in Komplexen Abfragen ohne das man zusätzliche “If” Statements benötigt, die prüfen ob der Wert Null ist.

Natürlich gibt es noch mehr features mit C# 6, aber diese verwende ich nur selten. Nur die oben genannten Features habe ich in meiner täglichen Arbeit aktiv mit eingebunden und möchte diese aktuell nicht mehr missen.

Code mit T4 Templates in Visual Studio generieren


Die meisten haben T4 Templates (Text Template Transformation Toolkit) bestimmt schon verwendet ohne zu wissen das es sich dabei um die Dateien mit der Endung “*.tt” handelt. Wenn man z.B. das Entity Framework verwendet wird im Hintergrund zur Entity Generierung ein T4 Template verwendet und auch bei ASP.NET MVC werden für das Erstellen von Views und Controllern T4 Templates verwendet, die man auch bei Bedarf an seine eigenen Bedürfnisse anpassen kann.

1. Erstellen eines T4 Templates

Wenn man selbst ein T4 Template anlegen möchte geht dies problemlos mit Visual Studio unter “Neues Item” anlegen und das “Text Template” auswählen und einen passenden Namen vergeben. Standardmäßig erhält die Datei die mit dem T4 Template dann später erstellt wird, den gleichen Namen wie das T4 Template und erhält nur eine andere Endung, z.B. cs oder txt.

image

Es gibt zwei Möglichkeiten wie man das Erstellen der Codeausgabe anstoßen kann. Einmal kann man mit der rechten Maustaste auf das T4 Template im Solution Explorer klicken und “Run Custom Tool” auswählen und schon wird der Code (die Ausgabe) neu erstellt/generiert. (Bei einem leeren Template natürlich auch nur eine leere Datei, diese Datei befindet sich Standardmäßig “unterhalb” des T4 Templates, welches man “aufklappen” kann.)

image

Eine weitere Möglichkeit zum Erstellen der Ausgabe ist das einfache Abspeichern des T4 Templates, wenn dies im Visual Studio geöffnet ist, hier wird bei jedem Speichern versucht den Ausgabecode zu erstellen.

2. Visual Studio Support Syntax highlighting und IntelliSense

Leider bietet die Grundinstallation von Visual Studio kein Syntax highlighting oder IntelliSense für T4 Templates. Es sollte nach einer passenden Extension gesucht werden, wenn man selbst ein T4 Template erstellen möchte. Wenn man Besitzer einer Lizenz von Resharper ist, hat man glück, denn hier gibt es eine sehr gute Extension mit dem Namen “ForTea” und diese bietet Syntax highlighting und IntelliSense. Wenn man keine Resharper Lizenz hat, kann man auf die kostenlose Version von “DevArt T4Editor” zurückgreifen oder von “tangible T4 Editor”.

3. T4 Syntax/Markup und Aufbau

Wenn man eine neue T4 Datei erstellt sieht diese im Normalfall folgendermaßen aus

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".txt" #>

Die Erste Zeile “template” Enthält dabei allgemeine Informationen für das Template selbst. Wenn man “hostpsecific” auf True stellt, dann erhält man im Template zugriff auf eine weitere lokale Variable mit dem Namen “Host”, mit der man z.B. den Aktuellen Pfad des T4 Templates auslesen kann “this.Host.TemplateFile”.

Die Sprache in “language” ist die Sprache mit der im Template programmiert wird und es handelt sich NICHT um die Sprache der Ausgabedatei.

Mit “debug” auf True kann man im Template Regions für “#if DEBUG” anlegen außerdem werden die Sourcen und debugging Symbols für das T4 Template selbst abgelegt unter “C:\Users\%AccountName$\AppData\Local\Temp\”.

Durch “assembly” lassen sich Externe Assemblies einbinden die man für die Codeerstellung benötigt, diese müssen im GAC vorhanden sein damit diese hier direkt angegeben werden können ohne Pfad. Wenn man eigene DLLs einbinden möchte, die sich nicht im GAC befinden, muss der komplette Pfad zur DLL angegeben werden (eine relative Angabe ist nicht möglich!). Dabei kann auf die Variablen “TargetDir” oder “SolutionDir” zugegriffen werden z.B.

<#@ assembly name="$(TargetDir)ProxyGenerator.dll" #>
<#@ assembly name="$(SolutionDir)MySolutionName\bin\x86\Release\ProxyGenerator.dll" #>

Zum “namespace”  muss glaube ich nichts gesagt werden, dieser funktioniert wie in allen anderen .NET Klassen.

Wie bereits weiter oben beschrieben erstellt ein T4 Template normalerweise eine Datei.

image

Über “output” und der zugehörigen “extension” kann angegeben werden um welche Dateiendung es sich bei der generierten Datei handeln soll. Da es mit zusätzlichem Code auch möglich ist mehrere Ausgabedateien zu erstellen, möchte man evtl. nicht das eine Datei mir dem Namen des T4 Templates erstellt wird und hier kann man z.B.

<#@ output extension="//" #>

verwenden als “Hack” denn es wird in der Ausgabe zumindest nur eine Warnung angezeigt und kein Fehler. Es wird aber keine Standard Ausgabedatei mehr generiert.

image

4. Code Blöcke <#, <#= und <#+

Bisher handelte es sich immer um Blöcke die in das “<#@ … #>” eingefasst werden. Es gibt aber noch andere Blöcke.

Mit dem “<#= GetText() #>” wird einfach der Rückgabewert der Funktion oder der Wert einer Variable direkt in die Ausgabedatei geschrieben. Mit dem Block “<# var name=”Squad”;#> können Codeschnipsel ausgeführt werden, wie Variablen Deklarationen oder ForEach schleifen. Aus dem einfachen Template

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".txt" #>

<# var name = "Squad"; #>
Hallo mein Name ist <#=name#>Wuschel

Wird dann folgende Ausgabe erstellt

Hallo mein Name ist SquadWuschel

Die Deklaration von Funktionen oder Klassen ist nur im Block “<#+ string GetText() … #>” möglich.

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".txt" #>

<# var name = "Squad"; #>
Hallo mein Name ist <#=name#>Wuschel
<#= GetText() #>

<#+
    string GetText() { return "Neuer Text"; } 
#>

Dabei wird die folgende Ausgabedatei generiert

Hallo mein Name ist SquadWuschel
Neuer Text

Ein weiteres Beispiel unter Verwendung einer for Schleife

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".txt" #>

<# var name = "Squad";
   for (int i = 0; i < 5; i++)
   {
     this.Write("Text mit Write Erstellt Nr: " + i + "\r\n");    
#>
Hallo mein Name ist <#=name #>Wuschel und ich bin Nummer: <#=i#>
<#=GetText(i) #>
<# } #>

<#+ string GetText(int nummer)  {  return "Neuer Text Nummer: " + nummer;   }  #>

Damit wird die folgende Ausgabe erstellt

Text mit Write Erstellt Nr: 0
Hallo mein Name ist SquadWuschel und ich bin Nummer: 0
Neuer Text Nummer: 0
Text mit Write Erstellt Nr: 1
Hallo mein Name ist SquadWuschel und ich bin Nummer: 1
Neuer Text Nummer: 1
Text mit Write Erstellt Nr: 2
Hallo mein Name ist SquadWuschel und ich bin Nummer: 2
Neuer Text Nummer: 2
Text mit Write Erstellt Nr: 3
Hallo mein Name ist SquadWuschel und ich bin Nummer: 3
Neuer Text Nummer: 3
Text mit Write Erstellt Nr: 4
Hallo mein Name ist SquadWuschel und ich bin Nummer: 4
Neuer Text Nummer: 4

5. Debuggen von T4 Templates

Seit Visual Studio 2012 ist es auch möglich ein T4 Template direkt zu debuggen im Visual Studio. Wenn man mit der rechten Maustaste auf das T4 Template klickt gibt es einen Punkt “Debug T4 Template”, vorher sollte man aber noch den passenden Haltepunkt setzen, damit der Debugger auch weiß wo er halten soll.

image

Leider kann man nicht direkt über die Variablen im Template gehen um zu sehen welcher Wert gerade in der Variablen X steht. Wenn man aber das “Locals” Fenster öffnet stehen automatisch alle aktuellen Variablen zur Verfügung und man sieht die passenden Werte.

image

image

Hinweis: Wenn das Template etwas größer wird und man eine eigene DLL einbindet, die man parallel in der gleichen Solution entwickelt, dann gibt es beim Debuggen ein Problem. Denn wenn man ein T4 Template debuggt, wird ein eigener Prozess erstellt “T4VSHostProcess.exe”.

image

Und dieser Prozess wird nicht wieder geschlossen, wenn das Debuggen des T4 Templates vorbei ist. Wenn man aber in seinem T4 Template auf eine DLL aus der aktuellen Solution verweist, die auch jedes mal mit gebaut werden soll, dann kommt es zu einem Fehler das die DLL bereits verwendet wird.

<#@ assembly name="$(TargetDir)ProxyGenerator.dll" #>

Das kann mit dem folgenden Eintrag im T4 Template Eintrag umgangen werden

<#@ CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #>

Damit wird der T4VSHostProcess nach jedem Debuggen wieder geschlossen.

Quellen:

http://www.olegsych.com/2008/02/t4-template-directive/

http://www.olegsych.com/2008/02/t4-class-feature-blocks/

Wer noch weitere Tipps zum Arbeiten mit T4 Templates hat, freue ich mich immer gern über einen Kommentar.

System.Web.Helpers.Crypto – PasswortHash, Salt


Oft kommt man in die Verlegenheit Funktionen selbst zu schreiben, weil man nicht weiß das es hier z.B. bereits fertige Funktionen direkt vom .NET Framework gibt. Dazu gehört auch die Klasse Crypto. Diese Klasse stellt uns ein paar nette Funktionen zur Verfügung um einen Passwort Hash bzw. den Salt für Passwörter zu erstellen und ein Passwort auf seine Richtigkeit zu prüfen.

//Erstellen des Salts und des PW Hashes
string passwordSalt = Crypto.GenerateSalt();
string passwordHash = Crypto.HashPassword(string.Format("{0}{1}", "Das Password", passwordSalt));

//Logindaten Prüfen ob Hash mit PW übereinstimmt
if (Crypto.VerifyHashedPassword(passwordHash, string.Format("{0}{1}", "Das Password", passwordSalt)))
{
        //Login Success
}
 

So einfach kann es sein sich den Hash bzw. einen zufälligen Salt erstellen zu lassen.

Wer noch einmal nachlesen will/muss, warum man Passwörter nicht im Klartext ablegt, sondern als Hashwert speichert und man zusätzlich noch einen Salt verwendet, der kann hier das ganze noch einmal nachlesen.

Performance “verbessern” von Coded-Ui Tests für Webseiten


Die Möglichkeit auch Weboberflächen automatisiert zu Testen mit Coded-Ui, ist sehr einfach zu realisieren. Denn die Coded-Ui Oberflächentests über den IE sind ähnlich leicht umzusetzen wie Oberflächentests mit Coded-Ui für eine WPF Anwendung. Nur leider ist die Geschwindigkeit wenn man Daten aus der Oberfläche über das “BrowserWindow” Objekt abfragt sehr langsam.

Wenn man z.B. eine Tabelle mit Werten hat, die verglichen werden sollen, dann bleibt einem mit den Coded-Ui Objekten nichts anderes übrig, wie die Tabelle zu ermitteln und dann in der Tabelle z.B. über ein foreach row die einzelnen Zeilen bzw. Zellen abzufragen:

//Tabelle wurde vorher über die Coded-Ui Oberfläche direkt als Element eingebunden
HtmlTable statisticTable = UiStatisticsSummaryTbl();
//z.B. den  Inhalt aus einer Zelle Ermitteln um diesen später zu vergleichen
string text = statisticTable.GetCell(1, 1).InnerText;

Wenn man hier die Tabelle immer erneut oder auch nur einmalig nach bestimmten Werten durchsuchen muss, kann dies eine Beträchtliche Zeit in Anspruch nehmen.

Um dieses Problem zu umgehen, nutze ich für aufwendige inhaltliche Oberflächenüberprüfungen das HtmlAgilityPack und lasse mir den HTML Code des kompletten Browser Fensters zurückgeben und parse/überprüfe die Oberflächenwerte mit der Hilfe von XPath Ausdrücken.

Ermitteln des Aktuellen Browserfensterinhalts:

 /// <summary>
 /// Den aktuellen Browserfensterinhalt als HTMLDocument des Agility Packs zurückgeben.
 /// </summary>
 public static HtmlAgilityPack.HtmlDocument GetHtmlDocument(BrowserWindow window)
 {
     HtmlDocument document = new HtmlDocument(window);
     string text = (string)document.GetProperty("OuterHtml");

     if (!string.IsNullOrEmpty(text))
     {
         HtmlAgilityPack.HtmlDocument doc= new HtmlAgilityPack.HtmlDocument();
         doc.LoadHtml(text);
         return doc;
      }
            return null;
 }

Die Abfragen direkt über das HTML Dokument selbst dauern dann nur noch einen Bruchteil der Zeit wie die Coded-Ui Abfrage eines einzelnen Elements gedauert hat.

//Unser HTML ermitteln aus dem aktuellen Testbrowserfenster
HtmlAgilityPack.HtmlDocument doc = GetHtmlDocument(browserwindow);
HtmlAgilityPack.HtmlDocument node = new HtmlAgilityPack.HtmlDocument();
//Unsere Tabelle anhand der ID ermitteln
node.LoadHtml(doc.GetElementbyId("DefaultStatTSummaryTblId").InnerHtml);
//Alle Rows unserer Tabelle ermitteln (Achtung die Header tr werden auch mit ermittelt)
HtmlAgilityPack.HtmlNodeCollection rows = node.DocumentNode.SelectNodes("//tr");
//den passenden Inhalt ermitteln aus der passenden Zelle
string text = rows[1].SelectNodes(".//td")[1].InnerText;

Mit dieser Methode kann man natürlich nicht alle Oberflächentests durchführen, aber wenn es sich um aufwendige Inhaltsabfragen der Oberfläche handelt, dann kann man damit einiges an Zeit einsparen.

Serialisieren bzw. Deserialisieren von Objekten mit dem XmlSerializer


Wenn man ein Objekt mit C# und  XmlSerializer serialisiert, dann erhält man das serialisierte Objekt in einer XML Struktur als String zurück. Außerdem ist es möglich dieses XML Dokument über den XmlSerializer auch wieder zu deserialisieren und wieder das passende Objekt zu erhalten.

Ein einfacher Weg dies umzusetzen, stellen die folgenden drei Funktionen dar. Hier kann ein beliebiges “einfaches” Objekt von einem beliebigen Typ übergeben werden und serialisiert bzw. deserialisiert werden. Dabei handelt es sich nur um eine beispielhafte Umsetzung, um zu verdeutlichen wie einfach es sein kann ein Objekt in XML umzuwandeln.

/// <summary>
/// serialisieren der Übergebenen Daten
/// </summary>
/// <typeparam name="T">Der Typ der Serialisiert werden soll</typeparam>
/// <param name="obj">Das Objekt welches Serialisiert werden soll</param>
/// <returns>Serialisiertes Objekt als XML-String</returns>
public static string Serialize<T>(T obj)
{
    using (var writer = new StringWriter())
    {
        new XmlSerializer(obj.GetType()).Serialize(writer, obj);
        string xml = writer.GetStringBuilder().ToString();
        return xml;
    }
}

/// <summary>
/// Deserialisieren unseres Übergebenen XML Strings und als ref des Übergebenen Objektes zurückgeben
/// </summary>
/// <param name="xml">Der XML String aus dem das passende Objekt erstellt werden soll</param>
public static void Deserialize<T>(ref T obj, string xml)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    StringReader reader = new StringReader(xml);
    object deserialized = serializer.Deserialize(reader);
    obj = (T)deserialized;
}

/// <summary>
/// Deserialisieren unseres Übergebenen XML Strings und zurückgeben des passenden Objektes
/// </summary>
/// <param name="xml">Der XML String aus dem das passende Objekt erstellt werden soll</param>
public static T Deserialize<T>(string xml)
{
    T obj = (T)Activator.CreateInstance(typeof(T));
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    StringReader reader = new StringReader(xml);
    object deserialized = serializer.Deserialize(reader);
    return (T)deserialized;
}

VS 2012 Fake DLLs für Tests (stubs und shims)


Aktuell hatte ich das “Vergnügen” mich mit der Unit Test Testbarkeit eines Projektes auseinander zu setzten. Da ich bisher nur mit Oberflächentests (Coded Ui) zu tun hatte, war eine Recherche angesagt und hier bin ich über diverse Mocking Frameworks wie z.B. “Moq” gestoßen die für Unit Tests zwingend benötigt werden. Außerdem gibt es ein neues Visual Studio CTP Update 2 hier steht jetzt ein eigenes Framework zum erstellen von Fake DLLs für die Visual Studio Versionen 2012 Premium und Ultimate zur Verfügung, diese Fake DLLs können ergänzend zu den Mocking Frameworks eingesetzt werden um Units Tests zu erstellen.

Im Folgenden will ich nur meinen kurzen Ausflug zum Erstellen eines Fake HttpContextes mit shims von MS Zeigen, was ich ziemlich Cool fand. Kommt bei mir aktuell leider nicht zum Einsatz, aber ein kurzes Beispiel schadet nicht.

Um eine Fake DLL zu erstellen muss die Referenz zum aktuellen Testprojekt hinzugefügt werden und dann mit der Rechten Maustaste auf der jeweiligen Referenz kann eine Fake Bibliothek angelegt werden.

image

Wenn man dann z.B. im Programm den Zugriff auf den HttpContext nutzt.

  public static CurrentSession GetSession()
    {
        if (HttpContext.Current.Session["MySession"] == null)
        {
            HttpContext.Current.Session["MySession"] = new CurrentSession();
        }

        return (CurrentSession)HttpContext.Current.Session["MySession"];
    }

Und in einem Unit Test auf den HttpContext zugegriffen wird, dann existiert der in den Unit Tests nicht und muss “Simuliert” werden. Dazu können wir jetzt unsere Fake DLL von “System.Web” Nutzen. Ich habe hier eine Statische Funktion erstellt, da ich auf das gleiche Konstrukt noch öfter zugreifen muss.

public static void LoadCurrentSession()
{
     var session = new System.Web.SessionState.Fakes.ShimHttpSessionState();
     session.ItemGetString = key =>
     {
           if (key == "MySession")
           {
               return new CurrentSession();
            }
           return null;
      };

      var context = new ShimHttpContext();
      ShimHttpContext.CurrentGet = () =>
      {
         return context;
      };

       ShimHttpContext.AllInstances.SessionGet = p => { return session; };
}

Das Ganze muss dann im Test z.B. so aufgerufen werden:

using (ShimsContext.Create())
{
     LoadCurrentSession()
     
     //Test durchführen in dem z.b. auf den HttpContext.Current.Session zugefriffen wird,
     //Dann wird hier unser Fake Kontext verwendet.
}

Das Ganze geht auch wenn man auf die Items des aktuellen HttpContexts zugreifen will.

public static GetContextData()
{
    if (HttpContext.Current.Items["MyItem1"] == null)
    {
        HttpContext.Current.Items.Add("MyItem1", "Hallo");
    }

    return (string)HttpContext.Current.Items["MyItem1"];
}

Die passende Hilfsfunktion für den Test würde dann folgendermaßen aussehen

public static void LoadContextItem(string itemName)
{
      var context = new ShimHttpContext();
      ShimHttpContext.CurrentGet = () =>
      {
           return context;
       };

        ShimHttpContext.AllInstances.ItemsGet = (p) => { return new ListDictionary() {{ itemName, „blubb“}}; };
}

Wenn man dann im Test wieder auf den Kontext zugreift und sein Item haben möchte, dann kann man hier wieder folgendermaßen darauf zugreifen.

using (ShimsContext.Create())
{
    LoadContextItem("MyItem1");
    
    //Test durchführen und auf das Passende Item zugreifen

}

Quellen:

http://msdn.microsoft.com/en-us/library/hh549175.aspx

http://blogs.msdn.com/b/visualstudioalm/archive/2013/02/11/february-ctp-for-visual-studio-update-2.aspx

http://blog.christopheargento.net/2013/02/02/testing-untestable-code-thanks-to-ms-fakes/

C# Bitmaske mit Enum (Flags Attribute)


Bisher habe ich noch nie Gebrauch von einer Bitmaske gemacht, aber heute musste ich mich kurz mit der Thematik auseinandersetzten und wollte hier kurz zeigen was zu welchem Ergebnis führt, wenn man mit einer Bitmaske und einem Enum mit dem “Flags” Attribut arbeitet.

Als Beispiel habe ich mir ein Enum mit den Wochentagen Montag bis Sonntag erstellt, hier darf das Attribut “Flags” nicht vergessen werden, denn nur dann kann mit den Werten Bitweise gerechnet werden. (Was Bitweise genau bedeutet findet man im Netz genug Beispiele.)

[Flags]
public enum WeekDays
{
    Mon = 1,
    Tue = 2,
    Wed = 4,
    Thu = 8,
    Fri = 16,
    Sat = 32,
    Sun = 64
}

Ich werde im Folgenden einfach ein paar Beispiele Zeigen wie man z.B. Wochentage zu einer Weekdays Variable hinzufügt, entfernt und überprüft ob ein einzelner Wochentag enthalten ist oder mehrere Wochentage.

//Tage zu unserer Variablen hinzufügen
WeekDays days = WeekDays.Mon;
days |= WeekDays.Tue;
days |= WeekDays.Fri;
//geht auch so:
//WeekDays days = WeekDays.Mon |  WeekDays.Tue | WeekDays.Fri;

//Prüfen ob der "Tue" in unseren Tagen enhalten ist.
if (days.HasFlag(WeekDays.Tue))
{
    //Unsere Tage als Int ablegen um z.B. in der Db zu speichern
    int daysAsInt = ((int)days);

    //Unseren Int wert wieder umwandeln in die Tage die wir ausgewählt hatten
    WeekDays daysFromInt = (WeekDays)daysAsInt;

    //Prüfen ob unser umgewandelter Intwert auch noch den Freitag enthält
    if (daysFromInt.HasFlag(WeekDays.Fri))
    {
        //Wird erreicht, da der Freitag noch enthalten ist.
        string found = "found";
    }

    //Prüfen ob der Donnerstag enthalten ist.
    if (daysFromInt.HasFlag(WeekDays.Thu))
    {
        //Wird nicht erreicht, da kein Donnerstag enthalten ist.
        string notFound = "notFound";
    }
}

//Prüfen ob genau diese drei Tage enhalten sind
if (days == (WeekDays.Mon | WeekDays.Tue | WeekDays.Fri))
{
    //Wird erreicht, da genau die drei Tage enthalten sind.
    string allRights = "alle Tage enthalten";
}

//Prüfen ob genau diese beiden Tage enthalten sind
if (days == (WeekDays.Mon | WeekDays.Tue))
{
    //Wird nicht erreicht, da der "Fri" Fehlt und die
    //Objekt damit nicht gleich sind
    string allRights = "nicht alle Tage enthalten";
}

//Prüfen ob alle Tage enthalten sind
if (days == (WeekDays.Mon | WeekDays.Tue | WeekDays.Fri | WeekDays.Sat))
{
    //Wird nicht erreicht da ein Tag zuviel gesucht wird "Sat"
    string allRights = "nicht ein Tag enthalten";
}

//Prüfen ob in unserer Tageliste einer der drei Tage enthalten ist,
//da "Mon" enthalten ist, wird daysCheck1 größer 0 sein
WeekDays daysCheck1 = (days & (WeekDays.Mon | WeekDays.Sun| WeekDays.Sat));
if (daysCheck1 != 0)
{
    //Wird erreicht, da mind. einer der Tage "Mon" enthalten ist.
    string allRights = "mind ein Tag enthalten";
}

//Prüfen ob in unserer Tagesliste einer der drei Tage enthalten ist,
//da keiner der Tage enthalten ist wird daysCheck2 gleich 0 sein.
WeekDays daysCheck2 = (days & (WeekDays.Wed | WeekDays.Sun | WeekDays.Sat));
if (daysCheck2 != 0)
{
    //Wird nicht erreicht, da keiner der Tage enthalten ist.
    string allRights = "kein Tag enthalten";
}

//Direktes Prüfen ob "Mon" und "Tue" in der Liste enthalten sind.
if ( (days & (WeekDays.Mon | WeekDays.Tue)) != 0)
{
    //Wird erreicht, da mind. einer der Tage enthalten ist.
    string allRights = "alle Tage enthalten";
}

//Entfernen eines Tages
days -= WeekDays.Tue;

//Prüfen ob der Tag noch enthalten ist.
if (days.HasFlag(WeekDays.Tue))
{
    //Wird nicht erreicht, da kein Dienstag mehr enthalten ist.
    string notFound = "notFound";
}