Hay un patrón en las clases de C # ejemplificado por Dictionary.TryGetValue
y int.TryParse
: un método que devuelve un valor booleano que indica el éxito de una operación y un parámetro de salida que contiene el resultado real; Si la operación falla, el parámetro de salida se establece en nulo.
Supongamos que estoy usando referencias no nulables de C # 8 y quiero escribir un método TryParse para mi propia clase. La firma correcta es esta:
public static bool TryParse(string s, out MyClass? result);
Como el resultado es nulo en el caso falso, la variable de salida debe marcarse como nulable.
Sin embargo, el patrón Try generalmente se usa así:
if (MyClass.TryParse(s, out var result))
{
// use result here
}
Como solo entro en la rama cuando la operación tiene éxito, el resultado nunca debe ser nulo en esa rama. Pero debido a que lo marqué como anulable, ahora tengo que verificar eso o usar !
para anular:
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
}
Esto es feo y un poco poco ergonómico.
Debido al patrón de uso típico, tengo otra opción: mentir sobre el tipo de resultado:
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;
}
Ahora el uso típico se vuelve más agradable:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // no warning
}
pero el uso atípico no recibe la advertencia que debería:
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.
}
Ahora no estoy seguro de qué camino tomar aquí. ¿Hay alguna recomendación oficial del equipo de lenguaje C #? ¿Hay algún código CoreFX ya convertido en referencias no anulables que pueda mostrarme cómo hacer esto? (Fui a buscar TryParse
métodos. IPAddress
Es una clase que tiene uno, pero no se ha convertido en la rama maestra de corefx).
¿Y cómo se ocupa esto de un código genérico Dictionary.TryGetValue
? (Posiblemente con un MaybeNull
atributo especial de lo que encontré.) ¿Qué sucede cuando instancia una Dictionary
con un tipo de valor no anulable?
MyClass?
), y hacer un cambio con uncase MyClass myObj:
y (una opción todos)case null:
.