Существует закономерность в классах C # на примере Dictionary.TryGetValue
и int.TryParse
: метод , который возвращает логическое значение , указывающее успех операции и параметра из содержащего фактический результат; если операция не удалась, для параметра out устанавливается значение null.
Давайте предположим, что я использую ненулевые ссылки C # 8 и хочу написать метод TryParse для моего собственного класса. Правильная подпись заключается в следующем:
public static bool TryParse(string s, out MyClass? result);
Поскольку в ложном случае результат равен нулю, переменная out должна быть помечена как nullable.
Тем не менее, шаблон Try обычно используется так:
if (MyClass.TryParse(s, out var result))
{
// use result here
}
Поскольку я вхожу только в ветвь, когда операция завершается успешно, результат в этой ветке никогда не должен быть нулевым. Но поскольку я пометил его как nullable, теперь я должен либо проверить это, либо использовать !
для переопределения:
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?
), и переключиться на него с помощьюcase MyClass myObj:
и (опция все)case null:
.