Wir haben eine eigene Klasse welche unseren Datentyp darstellt. Diese möchten wir jetzt mit ein paar Typkonvertierungen versehen, allerdings nicht über Extension methods oder andere ausgelagerte Funktionen. Unser Datentyp sieht wie folgt aus:
class MyDataType
{
public string Wert { get; set; }
}
Der Einfachheit halber nur eine simple Property. Normalerweise hat man ja sehr viele Unterschiedliche Properties in seinem Datentyp. Wir möchten jetzt daraus z.B. einen SecureString machen, oder auch einfach den Wert loggen. Man könnte jetzt natürlich einfach schreiben:
MyDataType myTypeInstance = new MyDataType() { Wert = "hallo" };
Log(myTypeInstance.Wert);
Wobei unsere Logfunktion einen string-Parameter entgegennimmt der dann – wo auch immer – protokolliert wird.
Diese Verwendung ist aber spätestens bei komplexeren Datentypen einfach nur unhandlich. Deshalb wollen wir einfach schreiben können:
Log(myTypeInstance);
oder um daraus einen SecureString zu machen:
SecureString mySecString = (SecureString)myTypeInstance;
Die meisten Implementierungen (die ich bisher gesehen habe) setzen auf eine extra ausgelagerte Funktion oder Extension methods. Die ausgelagerten Funktionen haben einen Nachteil: Sie konvertieren einfach mal alles was man reinwirft. Dieses Verhalten haben wir aber eigentlich nicht bezweckt, oder wir wollen das einfach nicht, da wir ja beim Zeitpunkt des Codens die Verwendungsmöglichkeiten einfach nicht alle im Überblick haben kann oder auch nicht testen kann.
Gehen wir also über Extension methods. OK – damit haben wir im Idealfall schonmal den Basistyp eingegrenzt. Nachteil allerdings hier: Extension methods funktionieren erst ab .Net 3.5… Also stehen wir wieder am Anfang.
Wie gehen wir also nun an die Sache ran?
Die Lösung ist liegt auf der Hand und ist eigentlich so simpel, das es mich immer wieder verwundert das es so selten eingesetzt wird:
Innerhalb unseres Datentyps definieren wir zwei neue statische Funktionen zur Typumwandlung hinzu:
public static implicit operator string(MyDataType toConvert) { }
public static explicit operator SecureString(MyDataType toConvert) { }
Diese beiden Funktionen führen nun unsere gewünschten impliziten wie expliziten Konvertierungen aus.
Wir füllen diese beiden Methoden also wie folgt auf:
public static implicit operator string(MyDataType toConvert)
{
return toConvert.Wert;
}
public static explicit operator SecureString(MyDataType toConvert)
{
SecureString mySecureString = new SecureString();
foreach (char item in toConvert.Wert)
{
mySecureString.AppendChar(item);
}
return mySecureString;
}
Das heißt, dadurch gewinnen wir saubereren Code und klarere Strukturen, da die Umwandlungen direkt innerhalb der Typen definiert werden können. Sie sind also genau da, wo sie auch hingehören.
Das komplette Testprogamm hier:
class MyDataType
{
public string Wert { get; set; }
public static implicit operator string(MyDataType toConvert)
{
return toConvert.Wert;
}
public static explicit operator SecureString(MyDataType toConvert)
{
SecureString mySecureString = new SecureString();
foreach (char item in toConvert.Wert)
{
mySecureString.AppendChar(item);
}
return mySecureString;
}
}
class Program
{
static void Main(string[] args)
{
MyDataType myTypeInstance = new MyDataType() { Wert = "hallo" };
Log(myTypeInstance);
SecureString mySecString = (SecureString)myTypeInstance;
Log(mySecString.ToString());
Console.Read();
}
static void Log(string message)
{
Console.WriteLine(message);
}
}



