C#: Factory methode to create new instance

Angenommen, wir haben ein Objekt AppColor, welches uns beim Erstellen der gewünschten Farben hilft. Wir möchten die Möglichkeit besitzen, die Farben über die Parameter Red, Green, Blue und Alpha zu steuern. Weiter brauchen wir verschiedene Möglichkeiten, um das Objekt zu initialisieren – sprich zu erzeugen. Direkt mit allen Parametern RGBA, nur RGB oder den einzelnen Farben. Dies führt dazu, dass wir eine ganze Reihe an Konstruktoren im Objekt haben werden:

public AppColor(byte red = 0, byte green = 0, byte blue=0, byte alpha=0)
{
    Red = red;
    Green = green;
    Blue = blue;
    Alpha = alpha;
}
public AppColor(byte red, byte green, byte blue)
{
    Red = red;
    Green = green;
    Blue = blue;
    Alpha = 0;
}
public AppColor(byte red)
{
    Red = red;
    Green = 0;
    Blue = 0;
    Alpha = 0;
}
...

Eine viel elegantere Lösung können wir mit einer Fabrikmethode (Factory methode) erstellen. Dazu erstellen wir eine Sub-Klasse mit dem Namen Builder, welche sämtliche Parameter als einzelne Methode enthält und als Rückgabewert wieder sich selber enthält. Zusätzlich wird noch eine Methode Create benötigt, welche dann das eigentliche Objekt erstellt:

public class Builder
{
#region fields
private byte _red;
private byte _green;
private byte _blue;
private byte _alpha;

#endregion

#region methodes
public Builder Red(byte red)
{
    _red = red;
    return this;
}
public Builder Green(byte green)
{
    _green = green;
    return this;
}
public Builder Blue(byte blue)
{
    _blue = blue;
    return this;
}
public Builder Alpha(byte alpha)
{
    _alpha = alpha;
    return this;
} 

public AppColor Create()
{
    return new AppColor(_red, _green, _blue, _alpha);
}
#endregion
}

Welche Vorteile haben wir nun mit diesem Konstrukt? Jetzt haben wir die Möglichkeit, eine x-beliebige Kombination von Parameter zu verwenden, um das Objekt AppColor zu erstellen:

// Einzelne Farbe
AppColor colorRed = new AppColor.Builder().Red(255).Create();

// Gemischte Farbe
AppColor mixColor = new AppColor.Builder().Red(22).Green(25).Create();

// Gemischte Farbe
AppColor mixColor2 = new AppColor.Builder().Green(25).Blue(12).Create();

// Gemischte Farbe
AppColor mixColor3 = new AppColor.Builder().Red(255).Green(255).Blue(0).Alpha(215).Create();

...

Ganze Klasse

C#: Statements as expressions

if-Statement as expression

Normales if-Statement:

public static decimal GetPriceByStatement(decimal price, int quantity, bool isPremiumMember)
{
    decimal discountAmount = 0;

    if(quantity >= 12)
    {
        discountAmount += .1M;
    }
    if (isPremiumMember)
    {
        discountAmount += .20M;
    }

    return price * (1 - discountAmount);
}

Das if-Statement als expression:

public static decimal GetPriceByExpression(decimal price, int quantity, bool isPremiumMember)
{
    decimal discountAmount = (quantity >= 12 ? .1M : 0) 
                + (isPremiumMember ? .2M : 0);
    return price * (1 - discountAmount);
}

swtich-statements as expression

Normales switch-Statement:

public static decimal GetNumberOfAccessLevelStatement(AccessLevels accessLevels)
{
    decimal accessLevelNumber = 0;
    switch (accessLevels)
    {
        case AccessLevels.Low:
            accessLevelNumber =  100501;
            break;
        case AccessLevels.LowExtendSecurity:
            accessLevelNumber = 100511;
            break;
        case AccessLevels.Middle:
            accessLevelNumber = 100601;
            break;
        case AccessLevels.MiddleExtendSecurity:
            accessLevelNumber = 100611;
            break;
        case AccessLevels.High:
            accessLevelNumber = 100701;
            break;
        case AccessLevels.HighExtendSecurity:
            accessLevelNumber = 100711;
            break;
        default:
            accessLevelNumber = 0;
            break;
    }
    return accessLevelNumber;
}

Das switch-Statement als switch-expression:

public static decimal GetNumberOfAccessLevelExpression(AccessLevels accessLevels)
{
    decimal accessLevelNumber = accessLevels switch
    {
        AccessLevels.Low => 100501,
        AccessLevels.LowExtendSecurity => 100511,
        AccessLevels.Middle => 100601,
        AccessLevels.MiddleExtendSecurity => 100611,
        AccessLevels.High => 100701,
        AccessLevels.HighExtendSecurity => 100711,
        _ => 0,
    };
    return accessLevelNumber;
}

C#: Zeichenketten richtig vergleichen

Vergleiche die zwei Namen “ROBONAME” und inputName, aber ignoriere die Gross- und Kleinschreibung.

const string ROBONAME = "iRoby";
string inputName = "IROBY";


if (0 == string.Compare(ROBONAME, inputName, true))
{
    Console.WriteLine($"Die Namen {ROBONAME} und {inputName} sind gleich.");
}

Nützliches

C# reference: https://docs.microsoft.com/en-us/dotnet/api/system.string.compare?view=net-5.0

Best practices for comparing strings in .NET: https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings

C#: String-Interpolation

Mit dem Dollar-Zeichen definieren wir, dass es sich um einen “interpolated string” handelt.

Struktur:

{<interpolationExpression>[,<alignment>][:<formatString>]}

Beispiel: String mit einem formatierten Datum

var msg = $"Datum: {DateTime.Today:dd.MM.yyyy}";

Beispiel: String mit einem formatierten Dezimalwert:

var shortPi = $"Pi is {Math.PI:F3}";

Beispiel mit Sonderzeichen und einem “conditional operator”:

Als Ausgabe erhalten wir:

Nützliches

C# reference: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated

C#: Null-Forgiving Operator (!)

Null-forgiving oder null-suppression operator

Wenn die Null-Prüfung des Compilers aktiviert wurde (“enabled nullable annotation context”), wird das Ausrufezeichen “!” Verwenden, um bewusst einen Nullwert zu erlauben.

Den “nullable annotation context” aktivieren oder deaktivieren

Null-Prüfung des Compilers ein- ausschalten mit Preprocessor-Direktiven:

#nullable enable
#nullable disable

Die Null-Prüfung kann auch auf der Projektebene in der Projekt-Datei eingeschaltet werden:

Nach dem Aktivieren der Null-Prüfung zeigt der Compiler eine Warnung bei möglichen Nullwerten an:

Sollte ein bestimmter Wert auch Null sein dürfen, haben wir die Möglichkeit, den “Null-Forgiving Operator” zu verwenden:

Nützliches

C# reference: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-forgiving