У класах C # є зразок, який ілюструється методом Dictionary.TryGetValue
та int.TryParse
: методом, який повертає булеве значення, що вказує на успіх операції, і вихідний параметр, що містить фактичний результат; якщо операція не вдалася, параметр «out» встановлюється на нуль.
Припустимо, я використовую ненульові посилання C # 8 і хочу написати метод TryParse для власного класу. Правильна підпис полягає в наступному:
public static bool TryParse(string s, out MyClass? result);
Оскільки результат є недійсним у хибному випадку, змінна out повинна бути позначена як нульова.
Однак модель "Спроба" зазвичай використовується так:
if (MyClass.TryParse(s, out var result))
{
// use result here
}
Оскільки я входжую у гілку лише тоді, коли операція проходить успішно, результат ніколи не повинен бути нульовим у цій гілці. Але оскільки я позначив це як нульовий, тепер я повинен або перевірити це, або використовувати !
для переосмислення:
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
}
Це некрасиво і трохи ненергономічно.
Через типову схему використання у мене є інший варіант: брехня про тип результату:
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;
}
Тепер типове використання стає приємнішим:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // no warning
}
але нетипове використання не отримує попередження, воно повинно:
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.
}
Тепер я не впевнений, куди йти сюди. Чи є офіційна рекомендація від мовної команди C #? Чи є вже якийсь код CoreFX, перетворений на нерегульовані посилання, який міг би показати мені, як це зробити? (Я пішов шукати TryParse
методи. IPAddress
Це клас, який має його, але він не був перетворений на головну гілку corefx.)
І як узагальнюючий код схожий Dictionary.TryGetValue
на це? (Можливо, із спеціальним MaybeNull
атрибутом із того, що я знайшов.) Що відбувається, коли я створюю інстанцію Dictionary
з типом значення, яке не зводиться до нуля?
MyClass?
), і зробіть на ньому перемикач з acase MyClass myObj:
і (необов'язково)case null:
.