Istnieje wzorzec w klasach C # zilustrowany przez Dictionary.TryGetValue
i int.TryParse
: metodę, która zwraca wartość logiczną wskazującą powodzenie operacji i parametr wyjściowy zawierający rzeczywisty wynik; jeśli operacja się nie powiedzie, parametr wyjściowy ma wartość null.
Załóżmy, że używam odwołań, które nie są zerowalne w języku C # 8, i chcę napisać metodę TryParse dla mojej własnej klasy. Poprawny podpis brzmi:
public static bool TryParse(string s, out MyClass? result);
Ponieważ w fałszywym przypadku wynik jest zerowy, zmienna wyjściowa musi być oznaczona jako pusta.
Jednak wzorzec Try jest ogólnie używany w następujący sposób:
if (MyClass.TryParse(s, out var result))
{
// use result here
}
Ponieważ wprowadzam gałąź tylko wtedy, gdy operacja się powiedzie, wynik nigdy nie powinien być pusty w tej gałęzi. Ale ponieważ oznaczyłem to jako zerowalne, muszę teraz to sprawdzić lub użyć !
do zastąpienia:
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
}
To jest brzydkie i trochę nieergonomiczne.
Ze względu na typowy wzorzec użytkowania mam inną opcję: kłamstwo na temat typu wyniku:
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;
}
Teraz typowe użycie staje się przyjemniejsze:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // no warning
}
ale nietypowe użycie nie wyświetla ostrzeżenia:
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.
}
Teraz nie jestem pewien, w którą stronę się udać. Czy istnieje oficjalna rekomendacja zespołu języka C #? Czy jest już jakiś kod CoreFX przekonwertowany na odwołania, które nie mają wartości zerowej, które mogłyby mi pokazać, jak to zrobić? (Poszedłem szukać TryParse
metod. IPAddress
Jest klasą, która ma jedną, ale nie została przekonwertowana w gałęzi master corefx.)
Jak radzi Dictionary.TryGetValue
sobie z tym ogólny kod ? (Prawdopodobnie ze specjalnym MaybeNull
atrybutem z tego, co znalazłem.) Co się stanie, gdy utworzę instancję Dictionary
z wartością o wartości innej niż null?
MyClass?
) i wykonaj na nim przełącznik za pomocą acase MyClass myObj:
i (opcjonalnie)case null:
.