Esiste un modello nelle classi C # esemplificato da Dictionary.TryGetValue
e int.TryParse
: un metodo che restituisce un valore booleano che indica il successo di un'operazione e un parametro out contenente il risultato effettivo; se l'operazione non riesce, il parametro out è impostato su null.
Supponiamo che io stia usando riferimenti non annullabili C # 8 e voglia scrivere un metodo TryParse per la mia classe. La firma corretta è questa:
public static bool TryParse(string s, out MyClass? result);
Poiché il risultato è nullo nel caso falso, la variabile out deve essere contrassegnata come nullable.
Tuttavia, il modello Try viene generalmente utilizzato in questo modo:
if (MyClass.TryParse(s, out var result))
{
// use result here
}
Poiché inserisco il ramo solo quando l'operazione ha esito positivo, il risultato non dovrebbe mai essere nullo in quel ramo. Ma poiché l'ho contrassegnato come nullable, ora devo verificarlo o utilizzare !
per sovrascrivere:
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
}
Questo è brutto e un po 'non ergonomico.
A causa del tipico modello di utilizzo, ho un'altra opzione: mentire sul tipo di risultato:
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;
}
Ora l'uso tipico diventa più bello:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // no warning
}
ma l'uso atipico non riceve l'avviso che dovrebbe:
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.
}
Ora non sono sicuro su quale strada andare qui. Esiste una raccomandazione ufficiale del team linguistico C #? Esiste già un codice CoreFX già convertito in riferimenti non annullabili che potrebbe mostrarmi come fare? (Sono andato alla ricerca di TryParse
metodi. IPAddress
È una classe che ne ha una, ma non è stata convertita nel ramo principale di corefx.)
E come fa il codice generico a Dictionary.TryGetValue
gestire questo? (Forse con un MaybeNull
attributo speciale da quello che ho trovato.) Cosa succede quando ho un'istanza di un Dictionary
tipo di valore non annullabile?
MyClass?
), e fai un interruttore su di esso con uncase MyClass myObj:
e (un'opzione)case null:
.