Heute einmal mit einem Antipattern, zum Thema tostring Methode. Viele kennen es und in vielen Programmiersprachen wird es unterstützt, die “.ToString()” Methode. Geliebt und oft und genutzt, doch es gibt einige Probleme bei der Nutzung der ToString() Methode. Die folgenden Beispiele sind in C# geschrieben, sind allerdings 1 zu 1 anwendbar in jeder weiteren Programmiersprache. Ich werde zunächst einige Beispiele auflisten, die zeigen sollen wie die ToString() Methode nicht genutzt werden sollte.
Beispiel 1: ToString als Konverter
1 2 3 4 5 6 7 8 | class Person { public string Name { get; set; } public int Age { get; set; } public override string ToString() { return JsonConvert.SerializeObject(this); } } |
In diesem Beispiel, wird die ToString() Methode als Json Serializer genutzt. Im weiterem verlauf wurde dieses Json persistiert. Und bei Bedarf wieder Deserialisiert (JsonConvert.DeserializeObject(jsonstring);). Auf dem erstem Blick spricht da auch nicht viel dagegen, sofern das gesamtes Dev Team nach dieser Konvention arbeiten möchte. Allerdings zeigt die Realität dass diese Verwendung zu Problemen führen wird. Sobald eine neue Klasse erstellt wird und der Entwickler nicht die ToString() Methode laut Konvention richtig füllt. In diesem Falle würde die default ToString Methode greifen, welche den Klassen Namen und die Version ausgibt. Bei der Deserialisierung kommt es dann zum bösen Erwachen. Die Daten können nicht rekonstruiert werden.
Für diesen Fall sollte immer das passende Converter geschrieben werden, sofern eine automatische Konvertierung nicht möglich ist. Siehe “Newtonsoft.Json.JsonConverter”
Beispiel 2: ToString als GUI Ausgabe
1 2 3 4 5 6 7 8 9 10 11 | class Person { public string Name { get; set; } public int Age { get; set; } public override string ToString() { return "Person: " + Name + " ist " + Age+ " Jahre alt."; } } .... currentPersonLabel.Text = person; .... |
Im diesem Beispiel wird die ToString Methode als GUI Hilfsklasse missbraucht. Hier wurde der zu anzeigende Text direkt in die ToString Methode geschrieben. Davon abgesehen das keine Ressourcen genutzt wurden, wird für einen einzigen GUI fall der Text statisch vorgegeben. Sobald die Person noch in weiteren GUI Elementen vorkommen soll, wird es schwierig. Zusätzlich ist nicht jedem Entwickler klar, dass eine Änderung des Textes in der ToString Methode eine Auswirkung auf GUI Element haben wird.
Auch hier ganz klar, sollte die ToString Methode nicht verwendet werden. Ein direkt Zugriff auf die Variablen wird wahrscheinlich schon ausreichen.
Beispiel 3: ToString zum Vergleichen
1 2 3 4 5 6 7 8 9 10 11 12 | class Person { public string Name { get; set; } public int Age { get; set; } public override string ToString() { return "Person: " + Name + " " + Age; } } .... if (person1.ToString()==person2.ToString()) .... |
Im dem letztem Beispiel wird die ToString Methode zum Vergleichen genutzt. Auch hier würde es zunächst funktionieren. Allerdings müsste die ToString Methode immer gepflegt werden. Sobald ein Property hinzukommt muss dies auch in der ToString Methode aufgelistet werden, ansonsten ist der Vergleich nicht korrekt. Der richtige Weg wäre hier das überschreiben der compare Methode.
1 | public virtual bool Equals (object obj); |
In Zuge dessen habe ich mich auf der Suche gemacht und einige Definitionen rausgesucht.
Für Java findet man auf “https://www.javatpoint.com/understanding-toString()-method” folgende Beschreibung:
If you want to represent any object as a string, toString() method comes into existence.
The toString() method returns the string representation of the object.
If you print any object, java compiler internally invokes the toString() method on the object. So overriding the toString() method, returns the desired output, it can be the state of an object etc. depends on your implementation.
Natürlich kann dies von einem oder dem andrem missverstanden werden. Speziell die äußerung “If you want to represent any object as a string” verleitet wohl den ein oder anderen, diese Methode für alles Mögliche zu verwenden. Besser wäre es gewesen die Aussage “If you print any object, java compiler internally invokes” hervorzuheben.
Ähnliches gilt für Microsoft (c#) “https://docs.microsoft.com/en-us/dotnet/api/system.object.tostring?view=netframework-4.8”
Object.ToString is the major formatting method in the .NET Framework. It converts an object to its string representation so that it is suitable for display. (For information about formatting support in the .NET Framework, see Formatting Types.) Default implementations of the Object.ToString method return the fully qualified name of the object\’s type.