In meinem System häufig mit Flughafen - Codes arbeiten I ( "YYZ"
, "LAX"
, "SFO"
, etc.), sind sie immer in dem exakt gleichen Format (3 Buchstaben, als Groß dargestellt). Das System verarbeitet in der Regel 25 bis 50 dieser (unterschiedlichen) Codes pro API-Anforderung, wobei insgesamt über tausend Zuweisungen vorgenommen werden. Sie werden durch viele Ebenen unserer Anwendung geleitet und häufig auf Gleichheit verglichen.
Wir haben angefangen, indem wir nur Strings herumgereicht haben, was ein bisschen gut funktioniert hat, aber wir haben schnell viele Programmierfehler bemerkt, indem wir irgendwo einen falschen Code eingegeben haben, wo der dreistellige Code erwartet wurde. Wir sind auch auf Probleme gestoßen, bei denen wir einen Vergleich durchführen sollten, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wurde. Dies führte zu Fehlern.
Aus diesem Grund habe ich beschlossen, keine Zeichenfolgen mehr weiterzugeben und eine Airport
Klasse mit einem einzigen Konstruktor zu erstellen , der den Flughafencode aufnimmt und validiert.
public sealed class Airport
{
public Airport(string code)
{
if (code == null)
{
throw new ArgumentNullException(nameof(code));
}
if (code.Length != 3 || !char.IsLetter(code[0])
|| !char.IsLetter(code[1]) || !char.IsLetter(code[2]))
{
throw new ArgumentException(
"Must be a 3 letter airport code.",
nameof(code));
}
Code = code.ToUpperInvariant();
}
public string Code { get; }
public override string ToString()
{
return Code;
}
private bool Equals(Airport other)
{
return string.Equals(Code, other.Code);
}
public override bool Equals(object obj)
{
return obj is Airport airport && Equals(airport);
}
public override int GetHashCode()
{
return Code?.GetHashCode() ?? 0;
}
public static bool operator ==(Airport left, Airport right)
{
return Equals(left, right);
}
public static bool operator !=(Airport left, Airport right)
{
return !Equals(left, right);
}
}
Dies machte unseren Code viel verständlicher und wir vereinfachten unsere Gleichheitsprüfungen, Wörterbuch- / Satzverwendungen. Wir wissen jetzt, dass, wenn unsere Methoden eine Airport
Instanz akzeptieren , die sich wie erwartet verhält, dies unsere Methodenprüfungen zu einer Nullreferenzprüfung vereinfacht hat.
Was mir jedoch aufgefallen ist, ist, dass die Speicherbereinigung viel häufiger ausgeführt wird, was ich auf viele Fälle zurückgeführt habe, in denen Airport
sie gesammelt wurde.
Meine Lösung hierfür war, die class
in eine umzuwandeln struct
. Meistens handelte es sich nur um eine Keyword-Änderung, mit Ausnahme von GetHashCode
und ToString
:
public override string ToString()
{
return Code ?? string.Empty;
}
public override int GetHashCode()
{
return Code?.GetHashCode() ?? 0;
}
Um den Fall zu behandeln, in dem default(Airport)
verwendet wird.
Meine Fragen:
War das Erstellen einer
Airport
Klasse oder Struktur im Allgemeinen eine gute Lösung, oder löse ich das falsche Problem / löse ich es auf die falsche Weise, indem ich den Typ erstelle? Wenn es keine gute Lösung ist, was ist eine bessere Lösung?Wie soll meine Anwendung mit Fällen umgehen, in denen die
default(Airport)
verwendet wird? Eine Art vondefault(Airport)
ist für meine Anwendung unsinnig, daher habe ichif (airport == default(Airport) { throw ... }
an Stellen gearbeitet, an denen das Abrufen einer Instanz vonAirport
(und ihrerCode
Eigenschaft) für den Vorgang von entscheidender Bedeutung ist.
Anmerkungen: Ich habe die Fragen zur C # / VB-Struktur überprüft . Und Verwenden Struktur oder nicht , bevor meine Frage zu stellen, aber ich denke , meine Fragen unterschiedlich genug sind , seinen eigenen Beitrag zu rechtfertigen.
default(Airport)
Problem zu lösen , besteht darin, Standardinstanzen einfach zu deaktivieren. Sie können dies tun, indem Sie einen parameterlosen Konstruktor schreiben und werfen InvalidOperationException
oder hinein NotImplementedException
.