1
votes

Kotlin, une instruction Elvis incorrecte est appelée lors de la vérification de la nullité imbriquée

J'ai constaté que dans le cas ci-dessous, le bloc Elvis est appelé alors qu'en fait il fait référence au contrôle de nullabilité externe

outer?.let {
    inner?.let {
        // do something
    } ?: System.out.println("Inner else")
} ?: System.out.println("Outer else")

À l'extérieur

L'ajout d'une branche Elvis au contrôle de nullabilité interne se comporte comme prévu:

val outer : String? = ""
val inner : String? = null

outer?.let {
    inner?.let {
        // do something
    }
} ?: System.out.println("Outer else")

Autre intérieur

Est-ce un bug de Kotlin?


0 commentaires

3 Réponses :


2
votes

Ce n'est pas un bug kotlin. a? .let {expr} prend la valeur nulle si

  1. a est nul, ou
  2. expr prend la valeur nulle

En assemblant des éléments, toute votre expression est évaluée comme suit:

  1. inner? .let {expr} est évalué à null, car inner est nul (cas 1 ci-dessus)
  2. donc external? .let {...} est évalué à null (cas 2 ci-dessus), car ce qu'il y a à l'intérieur des accolades est évalué à null (puce 11.)
  3. Donc, puisque ce qui reste de l'opérateur ?: est nul (puce 12.), l'expression elvis externe est évaluée.

Lorsque vous ajoutez un elvis après inner? .let {} , le external? .let {} ne renvoie plus null, il renvoie Unit , donc l'élvis externe n'est pas évalué. Est-ce clair?


0 commentaires

2
votes

L'opérateur Elvis n'est pas seulement destiné aux vérifications de nullité, il évaluera également le résultat de l'instruction et si null il exécutera la deuxième condition.

En d'autres termes, si inner? .let {} est évalué à null (si inner est nul ou si let < / code> retourne null), vous obtiendrez l'impression Outer else .

L'ajout de l'opérateur Elvis au bloc interne le confirme davantage, car il semble que quelque chose dans cette expression soit évalué à null.


0 commentaires

4
votes

Le code se comporte comme prévu. L'opérande de gauche de l'opérateur ?: dans votre cas est

inner?.let {
    // do something
} ?: System.out.println("Inner else")

externe n'est pas nul, donc le externe laisse Le bloc sera exécuté. inner est nul, donc le second let ne sera pas appelé et la valeur de retour du bloc externe sera nulle. Cela rend l'expression entière évaluée à null, donc l'opérande de droite de l'opérateur ?: est exécuté.

Dans votre deuxième exemple, la valeur du bloc externe est calculée comme

outer?.let {
    inner?.let {
        // do something
    }
}

Puisque inner est nul, l'opérande de droite du ?: sera appelé et évaluera à Unit , et c'est la valeur du bloc externe.


0 commentaires