¿Cuál es el idioma o las mejores prácticas de verificación nula de Dart?

82

Tengo la siguiente forma de asignación y verificaciones nulas para evitar búsquedas dobles en mis mapas.
¿Existe una forma mejor o más idiomática de hacer esto en Dart?

bool isConnected(a, b){
  List list;
  return (
    ((list = outgoing[a]) != null && list.contains(b)) ||
    ((list = incoming[a]) != null && list.contains(b))
  );
}
z5h
fuente

Respuestas:

116

A partir de Dart 1.12, los operadores con reconocimiento de nulos están disponibles para este tipo de situación:

bool isConnected(a, b) {
  bool outConn = outgoing[a]?.contains(b) ?? false;
  bool inConn = incoming[a]?.contains(b) ?? false;
  return outConn || inConn;
}

El ?.operador cortocircuita a nulo si el lado izquierdo es nulo, y el ??operador devuelve el lado izquierdo si no es nulo y el lado derecho en caso contrario.

La declaración

outgoing[a]?.contains(b)

por lo tanto, evaluará nullsi outgoing[a]es null, o el resultado booleano de contains(b)si no es.

Eso significa que la declaración resultante será una de las siguientes:

bool outConn = null ?? false; // false
bool outConn = false ?? false; // false
bool outConn = true ?? false; // true

Lo mismo se aplica al inConnbooleano, lo que significa que ambos inConny outConnestán garantizados como no nulos, lo que nos permite devolver el resultado de ||los dos.

Pixel elefante
fuente
Escribir outgoing[a]?.contains(b)es peligroso, al menos con la semántica Groovy, porque cuando outgoinges null, toda la expresión se evalúa como null. Entonces, de hecho, podría obtener algo como return (null || true), que se lanzará en modo verificado.
Ladicek
Gracias por el enlace del problema abierto.
z5h
@Ladicek Gracias por señalar eso. He incorporado el operador de fusión nula ( ??) en mi respuesta actualizada para dar cuenta de ese problema.
Pixel Elephant
2
Finalmente aterrizó \ o / github.com/gbracha/nullAwareOperators/blob/master/proposal.md
Günter Zöchbauer
Para verificar Campos de objetos, simplemente escriba object?.field ?? true. Donde verdadero puede ser lo que quieras.
Tilo
42

Ahora hay 4 operadores con conocimiento nulo

?? proporciona un valor predeterminado si el asunto es nulo

return subject ?? "defaultIfNull";

?? = establece el asunto en un valor predeterminado solo si el asunto es nulo

Esto es similar a ?? pero establece la variable sujeto a un valor predeterminado si es nulo.

subject ??= "defaultIfNull";

?. evitar una excepción si el sujeto es nulo al acceder a la propiedad del sujeto

object?.xdevolverá nulo si el objeto es nulo, object.xcausaría una excepción si el objeto fuera nulo

...? de una colección extendida, evite un elemento nulo en la lista final si la lista de temas es nula

el resultado de lo siguiente

[
  ...[1, 2],
  null,
]

es [1, 2, null]

para evitar el uso de valor nulo ...?

var resultingList = [
  ...[1, 2],
  ...?subjectList,
];
atreeon
fuente
2
Observación importante sobre el uso de ?. : si la referencia que acepta valores NULL atiene un método void method(), la siguiente sintaxis a?.method();ejecutará el método solo si ano es nulo.
Alex Semeniuk
@AlexSemeniuk, ¡gran punto! pero ¿hay alguna manera de hacer algo como esto >>> si a no es nulo ... entonces ejecute un método XYZ (), cuando este método no es miembro de la clase del objeto a ???
Yo Apps
@YoApps ¿Dejé esto claro que desea ejecutar un método que no es parte de la firma de clase? No es posible hacerlo en ningún idioma de programación orientada a objetos que yo conozca.
Alex Semeniuk
@AlexSemeniuk sí, también lo probé, no funcionó, así que volví a lo antiguoif(a!=null){XYZ();}
Yo Apps
1
@YoApps. Oh, te refieres a este código. No, no es posible en Dart.
Alex Semeniuk
14

Publicando lo siguiente, ya que terminé aquí buscando el título.

Según https://github.com/dart-lang/sdk/issues/66 , parece que la respuesta a "¿Cuál es el idioma de verificación nula de Dart o la mejor práctica?" es:

No hay ningún idioma de verificación nulo o mejores prácticas en el caso general. Si los operadores con reconocimiento de nulos no se ajustan a su caso, utilice la comparación directa como en if (object == null)o if (object != null).

stanm
fuente
1
ahora tienen opcionales :-)
Oliver Dixon
0
bool ok<T>(T obj) => obj != null;
bool nul<T>(T obj) => obj == null;
binarez
fuente
Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre por qué y / o cómo este código responde a la pregunta mejora su valor a largo plazo. Cómo responder . Saludos cordiales.
Elletlar