Es ist ein Muster , in C # Klassen veranschaulicht durch , Dictionary.TryGetValue
und int.TryParse
: ein Verfahren , das gibt einen booleschen angibt Erfolg einer Operation und einem Out - Parameter das tatsächliche Ergebnis enthält; Wenn der Vorgang fehlschlägt, wird der Parameter out auf null gesetzt.
Angenommen, ich verwende C # 8-Referenzen, die nicht nullwertfähig sind, und möchte eine TryParse-Methode für meine eigene Klasse schreiben. Die korrekte Signatur lautet:
public static bool TryParse(string s, out MyClass? result);
Da das Ergebnis im falschen Fall null ist, muss die Variable out als nullbar markiert werden.
Das Try-Muster wird jedoch im Allgemeinen folgendermaßen verwendet:
if (MyClass.TryParse(s, out var result))
{
// use result here
}
Da ich den Zweig nur betrete, wenn der Vorgang erfolgreich ist, sollte das Ergebnis in diesem Zweig niemals null sein. Aber da ich es als nullbar markiert habe, muss ich es jetzt entweder überprüfen oder !
zum Überschreiben verwenden:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // compiler warning, could be null
Console.WriteLine("Look: {0}", result!.SomeProperty); // need override
}
Das ist hässlich und ein bisschen unergonomisch.
Aufgrund des typischen Verwendungsmusters habe ich eine andere Option: Lüge über den Ergebnistyp:
public static bool TryParse(string s, out MyClass result) // not nullable
{
// Happy path sets result to non-null and returns true.
// Error path does this:
result = null!; // override compiler complaint
return false;
}
Jetzt wird die typische Verwendung schöner:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // no warning
}
atypische Nutzung wird jedoch nicht entsprechend gewarnt:
else
{
Console.WriteLine("Fail: {0}", result.SomeProperty);
// Yes, result is in scope here. No, it will never be non-null.
// Yes, it will throw. No, the compiler won't warn about it.
}
Jetzt bin ich mir nicht sicher, welchen Weg ich hier einschlagen soll. Gibt es eine offizielle Empfehlung des C # -Sprachteams? Gibt es CoreFX-Code, der bereits in nicht nullfähige Verweise konvertiert wurde, die mir zeigen könnten, wie das geht? (Ich habe nach TryParse
Methoden IPAddress
gesucht. Ist eine Klasse, die eine hat, aber sie wurde im Master-Zweig von corefx nicht konvertiert.)
Und wie geht generischer Code damit Dictionary.TryGetValue
um? (Möglicherweise mit einem speziellen MaybeNull
Attribut aus dem, was ich gefunden habe.) Was passiert, wenn ich einen Dictionary
mit einem nicht nullwertfähigen Werttyp instanziiere ?
MyClass?
), und schalten Sie es mit einemcase MyClass myObj:
und (optional) eincase null:
.